{"id":42237922,"url":"https://github.com/container-interop/service-provider","last_synced_at":"2026-01-27T03:43:12.691Z","repository":{"id":3828877,"uuid":"51035236","full_name":"container-interop/service-provider","owner":"container-interop","description":"[EXPERIMENTAL] Promoting container/framework interoperability through standard service providers","archived":false,"fork":false,"pushed_at":"2024-01-14T09:18:37.000Z","size":113,"stargazers_count":71,"open_issues_count":4,"forks_count":10,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-12-26T16:51:41.465Z","etag":null,"topics":["dependency-injection","php","psr","service-provider"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/container-interop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-03T22:27:25.000Z","updated_at":"2025-07-06T12:27:37.000Z","dependencies_parsed_at":"2023-12-18T22:00:51.987Z","dependency_job_id":"50a5e3df-49d7-48c3-ae02-b3507c1a8d15","html_url":"https://github.com/container-interop/service-provider","commit_stats":{"total_commits":42,"total_committers":4,"mean_commits":10.5,"dds":0.5,"last_synced_commit":"4969b9e49460690b7430b3f1a87cab07be61418a"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/container-interop/service-provider","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container-interop%2Fservice-provider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container-interop%2Fservice-provider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container-interop%2Fservice-provider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container-interop%2Fservice-provider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/container-interop","download_url":"https://codeload.github.com/container-interop/service-provider/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/container-interop%2Fservice-provider/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28800354,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T03:37:11.304Z","status":"ssl_error","status_checked_at":"2026-01-27T03:37:10.427Z","response_time":168,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependency-injection","php","psr","service-provider"],"created_at":"2026-01-27T03:43:11.966Z","updated_at":"2026-01-27T03:43:12.678Z","avatar_url":"https://github.com/container-interop.png","language":"PHP","readme":"# Standard Service Providers\n\nThis project attempts to define a common standard for service providers, aka \"bundles\" or \"modules\" in various frameworks.\n\nService providers are classes that provide service definitions to a [PSR-11](https://www.php-fig.org/psr/psr-11/) container.\n\nThe PSR depends on the PSR-11 [Container Interface](https://www.php-fig.org/psr/psr-11/#31-psrcontainercontainerinterface). Service providers operate on PSR-11 compatible containers.\n\n#### ⚠️ Work in progress\n\n\u003e the project is currently experimental and is being tried in frameworks, containers and modules until considered viable. Until a 1.0.0 release, the code in this repository is not stable. Expect breaking changes between versions such as `0.1.x` and `0.2.0`.\n\n#### 👉 Refer to the [current PSR draft](./PSR-XX-provider.md) for the PSR proposal itself.\n\n#### 🧐 Refer to the [PSR meta document](./PSR-XX-provider-meta.md) for the history and reasoning behind this proposal.\n\n#### 💬 Join us to review [open issues](/container-interop/service-provider/issues) or [participate in ongoing discussions](/container-interop/service-provider/discussions).\n\n\u003c!-- TODO resolve #67\n\n## Usage\n\nTo declare a service provider, simply implement the `ServiceProviderInterface` interface.\n\n```php\nuse Psr\\Container\\ServiceProviderInterface;\n\nclass MyServiceProvider implements ServiceProviderInterface\n{\n    public function getFactories()\n    {\n        return [\n            'my_service' =\u003e function(ContainerInterface $container) {\n                $dependency = $container-\u003eget('my_other_service');\n                return new MyService($dependency);\n            }\n        ];\n    }\n    \n    public function getExtensions()\n    {\n        return [\n            'my_extended_service' =\u003e function(ContainerInterface $container, $extendedService) {\n                $extendedService-\u003eregisterExtension($container-\u003eget('my_service'));\n                return $extendedService;\n            }\n        ];\n    }\n}\n```\n\n### Aliases\n\nTo alias a container entry to another, you can get the aliased entry from the container and return it:\n\n```php\nclass MyServiceProvider implements ServiceProviderInterface\n{\n    public function getFactories()\n    {\n        return [\n            'my_service' =\u003e fn() =\u003e new MyService(),\n            'my_alias' =\u003e fn(ContainerInterface $container) =\u003e $container-\u003eget('my_service'),\n        ];\n    }\n\n    // ...\n}\n```\n\n### Entry overriding\n\nOverriding an entry defined in another service provider is as easy as defining it again.\n\nModule A:\n\n```php\nclass A implements ServiceProviderInterface\n{\n    public function getFactories()\n    {\n        return [\n            'foo' =\u003e fn() =\u003e 'abc',\n        ];\n    }\n\n    // ...\n}\n```\n\nModule B:\n\n```php\nclass B implements ServiceProviderInterface\n{\n    public function getFactories()\n    {\n        return [\n            'foo' =\u003e fn() =\u003e 'def',\n        ];\n    }\n\n    // ...\n}\n```\n\nIf you register the service providers in the correct order in your container (A first, then B), then the entry `foo` will be `'def'` because B's definition will override A's.\n\n### Entry extension\n\nExtending an entry before it is returned by the container is done via the `getExtensions` method.\n\nModule A:\n\n```php\nclass A implements ServiceProviderInterface\n{\n    public function getFactories()\n    {\n        return [\n            'logger' =\u003e fn() =\u003e new MyLogger(),\n        ];\n    }\n    \n    // ...\n}\n```\n\nModule B:\n\n```php\nclass B implements ServiceProviderInterface\n{\n    public function getExtensions()\n    {\n        return [\n            'logger' =\u003e function (ContainerInterface $container, MyLogger $logger) {\n                $logger-\u003eaddHandler(new MyHandler());\n\n                return $logger;\n            },\n        ];\n    }\n\n    // ...\n}\n```\n\nThe second parameter of extensions SHOULD use type-hinting when applicable.\n\n```php\nfunction (ContainerInterface $container, MyLogger $logger)\n```\n\nIf a container passes a service that does not match the type hint, a `TypeError` will be thrown while bootstrapping the Container (in PHP 7+), or a catchable fatal error in PHP 5.\n\nThe second parameter of extensions CAN be nullable.\n\n```php\nfunction (ContainerInterface $container, ?MyLogger $logger)\n```\n\nThis allows an extension to handle a service that has been explicitly registered as `null` - for example:\n\n```php\nclass B implements ServiceProviderInterface\n{\n    public function getExtensions()\n    {\n        return [\n            'logger' =\u003e function (ContainerInterface $container, ?MyLogger $logger) {\n                if ($logger) {\n                    $logger-\u003eaddHandler(new MyHandler());\n                }\n\n                return $logger; // if `logger` is `null`, the extension will simply return `null`\n            },\n        ];\n    }\n\n    // ...\n}\n```\n\n--\u003e\n\n## Compatible projects\n\n### Projects consuming `v0.4` *service providers*\n\n- [Laravel service provider bridge](https://github.com/thecodingmachine/laravel-universal-service-provider/): Use container-interop's service-providers into any [Laravel](http://laravel.com/) application.\n- [Simplex](https://github.com/mnapoli/simplex): A [Pimple 3](https://github.com/silexphp/Pimple) fork with full [container-interop](https://github.com/container-interop/container-interop) compliance and cross-framework service-provider support.\n- [Service provider bridge bundle](https://github.com/thecodingmachine/service-provider-bridge-bundle): Use container-interop's service-providers into a Symfony container.\n- [Yaco](https://github.com/thecodingmachine/yaco): A compiler that generates container-interop compliant containers. Yaco can consume service-providers.\n\n### Packages providing `v0.4` *service providers*\n\n- [DBAL Module](https://github.com/thecodingmachine/dbal-universal-module): A module integrating [Doctrine DBAL](http://www.doctrine-project.org/projects/dbal.html) in an application using a service provider.\n- [Doctrine Annotations Module](https://github.com/thecodingmachine/doctrine-annotations-universal-module): A service provider for Doctrine's annotation reader.\n- [Glide Module](https://github.com/mnapoli/glide-module): A module integrating Glide in an application using a service provider.\n- [PSR-6 to Doctrine cache bridge module](https://github.com/thecodingmachine/psr-6-doctrine-bridge-universal-module): A service provider providing a Doctrine cache provider wrapping a PSR-6 cache pool.\n- [Slim-framework Module](https://github.com/thecodingmachine/slim-service-provider): A module integrating Slim framework v3 using a service provider.\n- [Stash Module](https://github.com/thecodingmachine/stash-universal-module): A service provider for the Stash PSR-6 caching library.\n- [Stratigility Module](https://github.com/thecodingmachine/stratigility-harmony): A service provider for the Stratigility PSR-7 middleware.\n- [Twig Module](https://github.com/thecodingmachine/twig-universal-module): A service provider for the Twig templating library.\n- [Whoops PSR-7 Middleware Module](https://github.com/thecodingmachine/whoops-middleware-universal-module): a service provider for the [Whoops](https://filp.github.io/whoops/) [PSR-7 middleware](https://github.com/franzliedke/whoops-middleware).\n\n\u003c!-- TODO resolve #65\n\n## Best practices\n\n### Managing configuration\n\nThe service created by a factory should only depend on the input parameters of the factory (`$container` and `$getPrevious`).\nIf the factory needs to fetch parameters, those should be fetched from the container directly.\n\n```php\nclass MyServiceProvider implements ServiceProviderInterface\n{\n    public function getFactories()\n    {\n        return [\n            'logger' =\u003e [ MyServiceProvider::class, 'createLogger' ],\n        ];\n    }\n    \n    public function getExtensions()\n    {\n        return [];\n    }\n\n    public static function createLogger(ContainerInterface $container)\n    {\n        // The path to the log file is fetched from the container, not from the service provider state.\n        return new FileLogger($this-\u003econtainer-\u003eget('logFilePath'));\n    }\n}\n```\n\n--\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontainer-interop%2Fservice-provider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcontainer-interop%2Fservice-provider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontainer-interop%2Fservice-provider/lists"}