diff --git a/CHANGELOG.md b/CHANGELOG.md index 79acf479..4aec0071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,16 @@ All notable changes to this project will be documented in this file, in reverse ### Added -- Nothing. +- [#180](https://github.com/zendframework/zend-servicemanager/pull/180) adds + explicit support for PSR-11 (ContainerInterface) by requiring + container-interop at a minimum version of 1.2.0, and adding a requirement on + psr/container 1.0. `Zend\ServiceManager\ServiceLocatorInterface` now + explicitly extends the `ContainerInterface` from both projects. + + Factory interfaces still typehint against the container-interop variant, as + changing the typehint would break backwards compatibility. Users can + duck-type most of these interfaces, however, by creating callables or + invokables that typehint against psr/container instead. ### Deprecated diff --git a/composer.json b/composer.json index a4189ce4..0200ab75 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ }, "require": { "php": "^5.6 || ^7.0", - "container-interop/container-interop": "~1.0", + "container-interop/container-interop": "^1.2", + "psr/container": "^1.0", "zendframework/zend-stdlib": "^3.1" }, "require-dev": { @@ -44,7 +45,8 @@ } }, "provide": { - "container-interop/container-interop-implementation": "^1.1" + "container-interop/container-interop-implementation": "^1.2", + "psr/container-implementation": "^1.0" }, "bin": [ "bin/generate-deps-for-config-factory", diff --git a/doc/book/psr-11.md b/doc/book/psr-11.md new file mode 100644 index 00000000..194aa9e9 --- /dev/null +++ b/doc/book/psr-11.md @@ -0,0 +1,58 @@ +# PSR-11 Support + +[container-interop/container-interop 1.2.0](https://github.com/container-interop/container-interop/releases/tag/1.2.0) +modifies its codebase to extend interfaces from [psr/container](https://github.com/php-fig/container) +(the official interfaces for [PSR-11](http://www.php-fig.org/psr/psr-11/)). If +you are on a pre-3.3.0 version of zend-servicemanager, update your project, and +receive container-interop 1.2, then zend-servicemanager can already act as a +PSR-11 provider! + +zend-servicemanager 3.3.0 requires at least version 1.2 of container-interop, +and _also_ requires psr/container 1.0 to explicitly signal that it is a PSR-11 +provider, and to allow removal of the container-interop dependency later. + +Version 4.0 will require only psr/container, and will update the various factory +interfaces and exception implementations to typehint against the PSR-11 +interfaces, which will require changes to any implementations you have. In the +meantime, you can [duck-type](https://en.wikipedia.org/wiki/Duck_typing) the +following factory types: + +- `Zend\ServiceManager\Factory\FactoryInterface`: use a callable with the + following signature: + + ```php + function ( + \Psr\Container\ContainerInterface $container, + string $requestedName, + array $options = null + ) + ``` + +- `Zend\ServiceManager\Factory\DelegatorFactoryInterface`: use a callable with + the following signature: + + ```php + function ( + \Psr\Container\ContainerInterface $container, + string $name, + callable $callback, + array $options = null + ) + ``` + +- `Zend\ServiceManager\Initializer\InitializerInterface`: use a callable with + the following signature: + + ```php + function ( + \Psr\Container\ContainerInterface $container, + $instance + ) + ``` + +Abstract factories _can not_ be duck typed, due to the additional `canCreate()` +method. + +You can also leave your factories as-is for now, and update them once +zend-servicemanager v4.0 is released, at which time we will be providing tooling +to help migrate your factories to PSR-11. diff --git a/mkdocs.yml b/mkdocs.yml index d9bdcecb..b778d955 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,6 +4,7 @@ pages: - index.md - 'Quick Start': quick-start.md - Reference: + - 'PSR-11 Support': psr-11.md - 'Configuring the service manager': configuring-the-service-manager.md - Delegators: delegators.md - 'Lazy services': lazy-services.md diff --git a/src/ServiceLocatorInterface.php b/src/ServiceLocatorInterface.php index 2f4f748d..34174c8f 100644 --- a/src/ServiceLocatorInterface.php +++ b/src/ServiceLocatorInterface.php @@ -7,13 +7,16 @@ namespace Zend\ServiceManager; -use Interop\Container\ContainerInterface; -use Interop\Container\Exception\ContainerException; +use Psr\Container\ContainerInterface as PsrContainerInterface; +use Psr\Container\ContainerExceptionInterface; +use Interop\Container\ContainerInterface as InteropContainerInterface; /** * Interface for service locator */ -interface ServiceLocatorInterface extends ContainerInterface +interface ServiceLocatorInterface extends + PsrContainerInterface, + InteropContainerInterface { /** * Build a service by its name, using optional options (such services are NEVER cached). @@ -25,7 +28,7 @@ interface ServiceLocatorInterface extends ContainerInterface * factory could be found to create the instance. * @throws Exception\ServiceNotCreatedException If factory/delegator fails * to create the instance. - * @throws ContainerException if any other error occurs + * @throws ContainerExceptionInterface if any other error occurs */ public function build($name, array $options = null); } diff --git a/test/ServiceManagerTest.php b/test/ServiceManagerTest.php index e8f34502..094951a6 100644 --- a/test/ServiceManagerTest.php +++ b/test/ServiceManagerTest.php @@ -9,6 +9,7 @@ use DateTime; use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; use stdClass; use Zend\ServiceManager\Factory\FactoryInterface; use Zend\ServiceManager\Factory\InvokableFactory; @@ -29,6 +30,12 @@ public function createContainer(array $config = []) return $this->creationContext; } + public function testServiceManagerIsAPsr11Container() + { + $container = $this->createContainer(); + $this->assertInstanceOf(ContainerInterface::class, $container); + } + public function testConfigurationCanBeMerged() { $serviceManager = new SimpleServiceManager([