### Install Laminas Service Manager with Composer Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/quick-start.md This command installs the Laminas Service Manager package using Composer, the dependency manager for PHP. Ensure Composer is installed on your system before running this command. ```bash composer require laminas/laminas-servicemanager ``` -------------------------------- ### Retrieve Shared Object Instance from Service Manager Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/quick-start.md Shows how to retrieve a shared instance of a service from the Service Manager using the `get()` method. By default, the Service Manager ensures that subsequent calls to `get()` for the same service return the exact same object instance. ```php $object = $serviceManager->get(stdClass::class); $object1 = $serviceManager->get(stdClass::class); $object2 = $serviceManager->get(stdClass::class); var_dump($object1 === $object2); // prints "true" ``` -------------------------------- ### Build Discrete Object Instance with Service Manager Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/quick-start.md Illustrates how to obtain a new, discrete instance of a service from the Service Manager using the `build()` method. Unlike `get()`, `build()` always returns a new object, even if the service has been requested before. ```php $object1 = $serviceManager->build(stdClass::class); $object2 = $serviceManager->build(stdClass::class); var_dump($object1 === $object2); // prints "false" ``` -------------------------------- ### Configure and Create Laminas Service Manager Instance Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/quick-start.md Demonstrates how to instantiate and configure the Laminas Service Manager. The constructor accepts an array of configuration options, such as defining factories for services. It uses stdClass::class and InvokableFactory as an example. ```php use Laminas\ServiceManager\ServiceManager; use Laminas\ServiceManager\Factory\InvokableFactory; use stdClass; $serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class, ], ]); ``` -------------------------------- ### Install laminas-cli for Servicemanager Commands Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/cli-commands/introduction.md This command installs the laminas-cli component, which is required to execute the CLI tooling provided by laminas-servicemanager starting from version 4.0.0. It's recommended to add this as a development dependency if only used for consuming these tools. ```bash composer require laminas/laminas-cli ``` -------------------------------- ### Migrating a v2 Factory to v3 with Proxy Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Example of updating a v2 FooFactory to v3 by implementing __invoke and having createService proxy to the new method. This allows for backward compatibility during the migration process. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\FactoryInterface; use Laminas\ServiceManager\ServiceLocatorInterface; class FooFactory implements FactoryInterface { public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { return new Foo($container->get(Bar::class)); } public function createService(ServiceLocatorInterface $services) { return $this($services, Foo::class); } } ``` -------------------------------- ### PHP: Migrating AbstractFactory to v3 Compatibility (v2 Example) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code demonstrates how to update a v2 `LenientAbstractFactory` to be compatible with v3. It involves adding the `canCreate` and `__invoke` methods and modifying existing methods to proxy to the new ones, ensuring a smooth transition. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\AbstractFactoryInterface; use Laminas\ServiceManager\ServiceLocatorInterface; class LenientAbstractFactory implements AbstractFactoryInterface { public function canCreate(ContainerInterface $container, $requestedName) { return class_exists($requestedName); } public function canCreateServiceWithName(ServiceLocatorInterface $services, $name, $requestedName) { return $this->canCreate($services, $requestedName); } public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { return new $requestedName(); } public function createServiceWithName(ServiceLocatorInterface $services, $name, $requestedName) { return $this($services, $requestedName); } } ``` -------------------------------- ### AbstractPluginManager Changes Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Explains the constructor, validation, and get method changes in AbstractPluginManager for version 3. ```APIDOC ## AbstractPluginManager Changes ### Description `AbstractPluginManager` in Laminas Service Manager v3 extends `ServiceManager` and incorporates several changes, including its constructor signature, validation mechanism, and the `get` method. ### Constructor - **Arguments**: - `container` (object): The parent container instance (usually the application-level `ServiceManager`). - `config` (array, optional): Configuration array for the plugin manager. - **Behavior**: - `validatePlugin()` is renamed to `validate()`. - The signature of `get()` changes. ### Validation (`validate` method) ```php public function validate($instance) { if (method_exists($this, 'validatePlugin')) { trigger_error(sprintf( '%s::validatePlugin() has been deprecated as of 3.0; please define validate() instead', get_class($this) ), E_USER_DEPRECATED); $this->validatePlugin($instance); return; } if (empty($this->instanceOf) || $instance instanceof $this->instanceOf) { return; } throw new InvalidServiceException(sprintf( 'Plugin manager "%s" expected an instance of type "%s", but "%s" was received', __CLASS__, $this->instanceOf, is_object($instance) ? get_class($instance) : gettype($instance) )); } ``` - **Purpose**: Ensures that plugin instances conform to expected types. For backward compatibility, it still supports `validatePlugin()`, but emits a deprecation notice. Defining `$instanceOf` is the preferred method for type validation. - **Example**: ```php protected $instanceOf = ValidatorInterface::class; ``` ### `get()` Method Signature Change - **Old Signature**: `public function get($name, $options = [], $usePeeringServiceManagers = true)` - **New Signature**: `public function get($name, array $options = null)` - **Impact**: The `$options` parameter must now be an array if provided, and peering service managers are no longer supported. ``` -------------------------------- ### ObserverAttachmentDelegator - Version 2 (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md An example delegator factory implementation compatible with version 2 of Laminas Service Manager, using the createDelegatorWithName method. ```php use Laminas\ServiceManager\DelegatorFactoryInterface; use Laminas\ServiceManager\ServiceLocatorInterface; class ObserverAttachmentDelegator implements DelegatorFactoryInterface { public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback) { $subject = $callback(); $subject->attach($serviceLocator->get(Observer::class); return $subject; } } ``` -------------------------------- ### Manual Delegation Example in PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/delegators.md Demonstrates manual instantiation and delegation of a 'Buzzer' object, including attaching an event listener. ```php $wrappedBuzzer = new Buzzer(); $eventManager = new Laminas\EventManager\EventManager(); $eventManager->attach('buzz', function () { echo "Stare at the art!\n"; }); $buzzer = new BuzzerDelegator($wrappedBuzzer, $eventManager); echo $buzzer->buzz(); // "Stare at the art!\nBuzz!" ``` -------------------------------- ### Complex Dependency Configuration Example (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/config-abstract-factory.md This comprehensive example shows how to configure multiple classes with nested dependencies using the ConfigAbstractFactory. It includes definitions for UserMapper, Cache, CacheAdapter, and Adapter, showcasing how dependencies are resolved across different factories and configurations. ```php // config/autoload/dependencies.php or anywhere that gets merged into global config return [ ConfigAbstractFactory::class => [ CacheAdapter::class => [], // no dependencies Cache::class => [ CacheAdapter::class, // dependency on the CacheAdapter key defined above ], UserMapper::class => [ Adapter::class, // will be called using normal factory defined below Cache::class, // defined above and will be created using this abstract factory ], ], 'service_manager' => [ 'factories' => [ Adapter::class => AdapterFactory::class, // normal factory not using above config ], ], ], ``` -------------------------------- ### Install ProxyManager LTS Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/lazy-services.md Installs the ProxyManager LTS package required for lazy service functionality using Composer. ```bash $ composer require friendsofphp/proxy-manager-lts ``` -------------------------------- ### ServiceLocatorInterface New Method (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Defines the new `build()` method added to the `ServiceLocatorInterface` in Laminas ServiceManager v3, which allows creating new service instances with optional arguments. ```php public function build($name, array $options = null) ``` -------------------------------- ### V3 Plugin Factory retrieving another plugin Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code snippet demonstrates the refactored v3 approach, where the plugin manager is retrieved from the creation context to access other plugins. ```php function ($services) { $plugins = $services->get('PluginManager'); $anotherPlugin = $plugins->get('AnotherPlugin'); return new Plugin($anotherPlugin); } ``` -------------------------------- ### V2 Plugin Factory with getServiceLocator Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code snippet demonstrates how a plugin factory in v2 would use `getServiceLocator()` to retrieve dependencies from the parent service locator. ```php function ($plugins) { $services = $plugins->getServiceLocator(); // pull dependencies from $services: $foo = $services->get('Foo'); $bar = $services->get('Bar'); return new Plugin($foo, $bar); } ``` -------------------------------- ### Manual Buzzer Delegation Example in PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/delegators.md An example demonstrating manual delegation of the Buzzer class. It manually creates instances of Buzzer, EventManager, and BuzzerDelegator, then attaches an event listener. ```php $wrappedBuzzer = new Buzzer(); $eventManager = new Laminas\EventManager\EventManager(); $eventManager->attach('buzz', function () { echo "Stare at the art!\n"; }); $buzzer = new BuzzerDelegator($wrappedBuzzer, $eventManager); echo $buzzer->buzz(); // "Stare at the art!\nBuzz!" ``` -------------------------------- ### Laminas ServiceManager v2 Lazy Service Configuration (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Demonstrates the configuration steps required to set up a lazy service in Laminas ServiceManager v2, involving a config service, LazyServiceFactoryFactory, and delegator factories. ```php use Laminas\ServiceManager\Proxy\LazyServiceFactoryFactory; $config = [ 'lazy_services' => [ 'class_map' => [ 'MyClass' => 'MyClass', ], 'proxies_namespace' => 'TestAssetProxy', 'proxies_target_dir' => 'data/proxies/', 'write_proxy_files' => true, ], ]; return [ 'services' => [ 'config' => $config, ], 'invokables' => [ 'MyClass' => 'MyClass', ], 'factories' => [ 'LazyServiceFactory' => LazyServiceFactoryFactory::class, ], 'delegators' => [ 'MyClass' => [ 'LazyServiceFactory', ], ], ]; ``` -------------------------------- ### Install Laminas CLI for AOT Factory Generation Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/cli-commands/generate-ahead-of-time-factories.md To use the `laminas servicemanager:generate-aot-factories` command, the `laminas/laminas-cli` package must be installed as a development dependency. This command adds the necessary package to your project's composer requirements. ```shell composer require --dev laminas/laminas-cli ``` -------------------------------- ### Mapping Lazy Services with mapLazyService (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Shows how to map lazy services using the `mapLazyService` method in Laminas ServiceManager, which can be used after initial proxy configuration. ```php $container->mapLazyService('MyClass', 'MyClass'); // or, more simply: $container->mapLazyService('MyClass'); ``` -------------------------------- ### Migrating Laminas Service Manager Initializer from v2 to v3 (Class Implementation) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Demonstrates how to update an existing v2 InitializerInterface implementation to be compatible with v3. This involves implementing the __invoke method and having the initialize method proxy to it. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\InitializerInterface; use Laminas\ServiceManager\ServiceLocatorInterface; class FooInitializer implements InitializerInterface { public function __invoke(ContainerInterface $container, $instance) { if (! $instance implements FooAwareInterface) { return $instance; } $container->setFoo($services->get(FooInterface::class); return $instance; } public function initializer($instance, ServiceLocatorInterface $services) { return $this($services, $instance); } } ``` -------------------------------- ### Defining a Custom Factory Class for Object Creation Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/configuring-the-service-manager.md Provides an example of defining a separate class that implements the FactoryInterface (or has an __invoke method) to handle the creation of a specific service. This promotes cleaner and more organized code. ```php // In MyObjectFactory.php file class MyObjectFactory implements FactoryInterface { public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { $dependency = $container->get(stdClass::class); return new MyObject($dependency); } } // or without implementing the interface: class MyObjectFactory { public function __invoke(ContainerInterface $container, $requestedName) { $dependency = $container->get(Dependency::class); return new MyObject($dependency); } } // When creating the service manager: $serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class, MyObject::class => MyObjectFactory::class ] ]); ``` -------------------------------- ### Laminas Service Manager InitializerInterface Signature v2 vs v3 Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Compares the method signatures for the InitializerInterface in Laminas Service Manager v2 and v3. The v2 signature takes an instance and a ServiceLocatorInterface, while v3 uses the __invoke magic method with a ContainerInterface and the instance. ```php public function initialize($instance, ServiceLocatorInterface $serviceLocator) ``` ```php public function __invoke(ContainerInterface $container, $instance) ``` -------------------------------- ### Enable ConfigAbstractFactory in Configuration (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/config-abstract-factory.md This code illustrates how to enable the ConfigAbstractFactory within service manager configuration arrays. It shows examples for both laminas-mvc and mezzio/ConfigProvider setups. ```php // laminas-mvc: 'service_manager' => [ 'abstract_factories' => [ ConfigAbstractFactory::class, ], ], // mezzio or ConfigProvider consumers: 'dependencies' => [ 'abstract_factories' => [ ConfigAbstractFactory::class, ], ], ``` -------------------------------- ### Final v3 Factory Implementation (Invokable) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md The final version 3 implementation of the FooFactory after removing migration artifacts. It now solely implements the FactoryInterface via the __invoke method and uses the new namespaced interface. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\Factory\FactoryInterface; // <-- note the change! class FooFactory implements FactoryInterface { public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { return new Foo($container->get(Bar::class)); } } ``` -------------------------------- ### V3 Plugin Factory with updated context Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code snippet shows the updated v3 plugin factory, where the creation context is used directly instead of `getServiceLocator()`, eliminating deprecation notices. ```php function ($services) { // pull dependencies from $services: $foo = $services->get('Foo'); $bar = $services->get('Bar'); return new Plugin($foo, $bar); } ``` -------------------------------- ### Build Discrete Validator Instances with Laminas Service Manager Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Demonstrates using the `build()` method to create two separate instances of `LaminasValidatorBetween`, each with distinct configuration options for 'min', 'max', and 'inclusive'. This highlights `build()`'s capability to generate unshared, configured service instances. ```php use Laminas\Validator\Between; $between = $container->build(Between::class, [ 'min' => 5, 'max' => 10, 'inclusive' => true, ]); $alsoBetween = $container->build(Between::class, [ 'min' => 0, 'max' => 100, 'inclusive' => false, ]); ``` -------------------------------- ### ObserverAttachmentDelegator - Version 3 Migration (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md A transitional implementation of ObserverAttachmentDelegator for Laminas Service Manager version 3, supporting both the old and new signatures during migration. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\DelegatorFactoryInterface; use Laminas\ServiceManager\ServiceLocatorInterface; class ObserverAttachmentDelegator implements DelegatorFactoryInterface { public function __invoke(ContainerInterface $container, $requestedName, callable $callback, array $options = null) { $subject = $callback(); $subject->attach($container->get(Observer::class); return $subject; } public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback) { return $this($serviceLocator, $requestedName, $callback); } } ``` -------------------------------- ### PluginManagerInterface API Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Details the PluginManagerInterface, which extends ServiceLocatorInterface and adds a validate method. ```APIDOC ## PluginManagerInterface API ### Description The `PluginManagerInterface` defines the public API for plugin managers in Laminas Service Manager version 3. It extends the `ServiceLocatorInterface` and introduces a `validate` method for instance validation. ### Methods #### validate ```php /** * Validate an instance * * @param object $instance * @return void * @throws InvalidServiceException If created instance does not respect the * constraint on type imposed by the plugin manager */ public function validate($instance); ``` - **Description**: Validates a created plugin instance. It throws an `InvalidServiceException` if the instance does not meet the expected type constraints defined by the plugin manager. ``` -------------------------------- ### PHP: AbstractFactoryInterface v2 Signature Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This code snippet shows the v2 signature of the AbstractFactoryInterface in PHP, which includes `canCreateServiceWithName` and `createServiceWithName` methods. These methods expect a `ServiceLocatorInterface` and service names as arguments. ```php interface AbstractFactoryInterface { /** * Determine if we can create a service with name * * @param ServiceLocatorInterface $serviceLocator * @param $name * @param $requestedName * @return bool */ public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName); /** * Create service with name * * @param ServiceLocatorInterface $serviceLocator * @param $name * @param $requestedName * @return mixed */ public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName); } ``` -------------------------------- ### Laminas ServiceManager v3 Lazy Service Configuration (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Illustrates the simplified configuration for lazy services in Laminas ServiceManager v3, where lazy service configuration can be passed directly and the ServiceManager handles the LazyServiceFactory. ```php use Laminas\ServiceManager\Factory\InvokableFactory; use Laminas\ServiceManager\Proxy\LazyServiceFactory; return [ 'factories' => [ 'MyClass' => InvokableFactory::class, ], 'delegators' => [ 'MyClass' => [ LazyServiceFactory::class, ], ], 'lazy_services' => [ 'class_map' => [ 'MyClass' => 'MyClass', ], 'proxies_namespace' => 'TestAssetProxy', 'proxies_target_dir' => 'data/proxies/', 'write_proxy_files' => true, ], ]; ``` -------------------------------- ### Example Delegated Service (Buzzer) in PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/delegators.md A simple PHP class 'Buzzer' with a 'buzz' method, serving as the base object to be delegated. ```php class Buzzer { public function buzz() { return 'Buzz!'; } } ``` -------------------------------- ### Configuring Factories with InvokableFactory and Custom Factory Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/configuring-the-service-manager.md Shows how to configure the 'factories' array in the Service Manager. It includes an example using Laminas\ServiceManager\Factory\InvokableFactory for simple objects and a custom factory class for more complex object creation. ```php use Laminas\ServiceManager\Factory\InvokableFactory; use Laminas\ServiceManager\ServiceManager; use stdClass; $serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class, MyObject::class => MyObjectFactory::class, ], ]); ``` -------------------------------- ### Laminas Service Manager Initializer v3 (Post-Migration Class) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Shows the final state of a Laminas Service Manager initializer class after migrating to version 3 and removing migration artifacts. It implements the new InitializerInterface with the __invoke method. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\Initializer\InitializerInterface; // <-- note the change! class FooInitializer implements InitializerInterface { public function __invoke(ContainerInterface $container, $instance) { if (! $instance implements FooAwareInterface) { return $instance; } $container->setFoo($services->get(FooInterface::class); return $instance; } } ``` -------------------------------- ### Generate Service and Factory Configuration - PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/cli-commands/generate-ahead-of-time-factories.md Example of a PHP configuration file generated by the Laminas-ServiceManager CLI command. This file consolidates service and factory entries for a project's container and plugin-managers. It follows a specific structure for 'service_manager' and other service categories like 'validators'. ```php return [ 'service_manager' => [ 'factories' => [ MyService::class => GeneratedMyServiceFactory::class, ], ], 'validators' => [ 'factories' => [ MyValidator::class => GeneratedMyValidatorFactory::class, ], ], ]; ``` -------------------------------- ### Laminas Service Manager v2 FactoryInterface Signature Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md The signature of the FactoryInterface in Laminas Service Manager version 2, which defined a single createService method accepting a ServiceLocatorInterface. ```php interface FactoryInterface { /** * Create service * * @param ServiceLocatorInterface $serviceLocator * @return mixed */ public function createService(ServiceLocatorInterface $serviceLocator); } ``` -------------------------------- ### Laminas Service Manager Migration Test Case Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHPUnit test case uses Laminas\ServiceManager\Test\CommonPluginManagerTrait to test the migration of a plugin manager, verifying configuration, exception handling, and alias resolution. ```php use MyNamespace\ObserverInterface; use MyNamespace\ObserverPluginManager; use MyNamespace\Exception\RuntimeException; use PHPUnit_Framework_TestCase as TestCase; use Laminas\ServiceManager\ServiceManager; use Laminas\ServiceManager\Test\CommonPluginManagerTrait; class MigrationTest extends TestCase { use CommonPluginManagerTrait; protected function getPluginManager() { return new ObserverPluginManager(new ServiceManager()); } protected function getV2InvalidPluginException() { return RuntimeException::class; } protected function getInstanceOf() { return ObserverInterface::class; } } ``` -------------------------------- ### DelegatorFactoryInterface - New Signature (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md The new signature of the DelegatorFactoryInterface in Laminas Service Manager, utilizing __invoke for creating delegates and supporting additional options. ```php interface DelegatorFactoryInterface { /** * A factory that creates delegates of a given service * * @param ContainerInterface $container * @param string $name * @param callable $callback * @param null|array $options * @return object */ public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null); } ``` -------------------------------- ### ObserverAttachmentDelegator - Version 3 Final (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md The final implementation of ObserverAttachmentDelegator for Laminas Service Manager version 3, adhering to the new DelegatorFactoryInterface signature and removing migration artifacts. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\Factory\DelegatorFactoryInterface; // <-- note the change! class ObserverAttachmentDelegator implements DelegatorFactoryInterface { public function __invoke(ContainerInterface $container, $requestedName, callable $callback, array $options = null) { $subject = $callback(); $subject->attach($container->get(Observer::class); return $subject; } } ``` -------------------------------- ### DelegatorFactoryInterface - Old Signature (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md The previous signature of the DelegatorFactoryInterface in Laminas Service Manager, used for creating delegates of a given service. ```php interface DelegatorFactoryInterface { /** * A factory that creates delegates of a given service * * @param ServiceLocatorInterface $serviceLocator the service locator which requested the service * @param string $name the normalized service name * @param string $requestedName the requested service name * @param callable $callback the callback that is responsible for creating the service * * @return mixed */ public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback); } ``` -------------------------------- ### PHP: AbstractFactoryInterface v3 Signature Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This code snippet displays the v3 signature of the AbstractFactoryInterface in PHP. It now extends `FactoryInterface` and the primary method for checking service creation is `canCreate`, which takes a `ContainerInterface` and the requested service name. ```php interface AbstractFactoryInterface extends FactoryInterface { /** * Does the factory have a way to create an instance for the service? * * @param ContainerInterface $container * @param string $requestedName * @return bool */ public function canCreate(ContainerInterface $container, $requestedName); } ``` -------------------------------- ### PHP: Final v3 AbstractFactory Implementation Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code shows the final version of the `LenientAbstractFactory` after upgrading to v3 of Laminas Service Manager. It implements the new `AbstractFactoryInterface` (noting the changed namespace) and includes only the v3-required methods: `canCreate` and `__invoke`. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\Factory\AbstractFactoryInterface; // <-- note the change! class LenientAbstractFactory implements AbstractFactoryInterface { public function canCreate(ContainerInterface $container, $requestedName) { return class_exists($requestedName); } public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { return new $requestedName(); } } ``` -------------------------------- ### PHP: Default Shared Service Instance Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/configuring-the-service-manager.md Demonstrates that by default, the Service Manager returns the same instance of a service when requested multiple times using the `get()` method. This is confirmed by comparing the two obtained instances. ```php $serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class ] ]); $object1 = $serviceManager->get(stdClass::class); $object2 = $serviceManager->get(stdClass::class); var_dump($object1 === $object2); // prints "true" ``` -------------------------------- ### v2 Service Manager Configuration Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code snippet illustrates the configuration structure for the Laminas Service Manager in version 2. It includes common configuration keys like 'services', 'aliases', 'invokables', and 'factories'. ```php [ 'services' => [ // service name => instance pairs ], 'aliases' => [ // alias => service name pairs ], 'invokables' => [ // service name => class name pairs ], 'factories' => [ // service name => factory pairs ], 'abstract_factories' => [ // abstract factories ], 'initializers' => [ // initializers ], 'delegators' => [ // service name => [ delegator factories ] ], 'shared' => [ // service name => boolean ], 'share_by_default' => boolean, ] ``` -------------------------------- ### V2 Plugin Factory retrieving another plugin Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code snippet illustrates an older pattern where a plugin factory accessed another plugin via the passed plugin manager instance. ```php function ($plugins) { $anotherPlugin = $plugins->get('AnotherPlugin'); return new Plugin($anotherPlugin); } ``` -------------------------------- ### Service Manager Configuration with Delegators in PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/delegators.md An example of configuring Laminas Service Manager to use a delegator factory. It registers Buzzer::class with InvokableFactory and BuzzerDelegatorFactory::class as its delegator. ```php use Laminas\ServiceManager\Factory\InvokableFactory; use Laminas\ServiceManager\ServiceManager; $serviceManager = new Laminas\ServiceManager\ServiceManager([ 'factories' => [ Buzzer::class => InvokableFactory::class, ], 'delegators' => [ Buzzer::class => [ BuzzerDelegatorFactory::class, ], ], ]); // now, when fetching Buzzer, we get a BuzzerDelegator instead $buzzer = $serviceManager->get(Buzzer::class); $buzzer->buzz(); // "Stare at the art!\nBuzz!" ``` -------------------------------- ### Example Delegator Class (BuzzerDelegator) in PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/delegators.md A PHP class extending the delegated service to intercept method calls. It uses an event manager to trigger events before executing the original method. ```php use Laminas\EventManager\EventManagerInterface; class BuzzerDelegator extends Buzzer { protected $realBuzzer; protected $eventManager; public function __construct(Buzzer $realBuzzer, EventManagerInterface $eventManager) { $this->realBuzzer = $realBuzzer; $this->eventManager = $eventManager; } public function buzz() { $this->eventManager->trigger('buzz', $this); return $this->realBuzzer->buzz(); } } ``` -------------------------------- ### Update Plugin Manager Configuration in PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code demonstrates how to configure an ObserverPluginManager after migrating to Laminas Service Manager v3. It extends AbstractPluginManager, defines $instanceOf, $aliases, and $factories, reflecting the updated structure and best practices. ```php use Laminas\ServiceManager\AbstractPluginManager; use Laminas\ServiceManager\Factory\InvokableFactory; class ObserverPluginManager extends AbstractPluginManager { protected $instanceOf = ObserverInterface::class; protected $aliases = [ 'mail' => MailObserver::class, 'Mail' => MailObserver::class, 'log' => LogObserver::class, 'Log' => LogObserver::class, ]; protected $factories = [ MailObserver::class => InvokableFactory::class, LogObserver::class => InvokableFactory::class, ]; } ``` -------------------------------- ### Verify Lazy Service Instantiation Delay Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/lazy-services.md This code snippet iterates multiple times to get the Buzzer service and then calls its 'buzz' method. It demonstrates that the 5-second delay from the constructor is postponed until the 'buzz' method is invoked, confirming lazy loading. ```php use MyApp\Buzzer; for ($i = 0; $i < 100; $i += 1) { $buzzer = $serviceManager->get(Buzzer::class); echo "created buzzer $i\n"; } echo $buzzer->buzz(); ``` -------------------------------- ### Plugin Manager Invokables Migration to Factories and Aliases (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code snippet shows the transformation of an 'invokables' property in a v2 plugin manager to 'aliases' and 'factories' in v3. It demonstrates how to correctly configure services that were previously handled by invokables. ```php use Laminas\ServiceManager\Factory\InvokableFactory; class AdapterPluginManager extends AbstractPluginManager { protected $aliases = [ 'bcmath' => Adapter\Bcmath::class, 'gmp' => Adapter\Gmp::class, ]; protected $factories = [ Adapter\BcMath::class => InvokableFactory::class, Adapter\Gmp::class => InvokableFactory::class, ]; } ``` -------------------------------- ### Laminas Service Manager v3 Plugin Manager Migration Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code demonstrates the migration of a Laminas Service Manager plugin manager to version 3, incorporating changes to configuration, validation, and property handling for compatibility with both v2 and v3. ```php namespace MyNamespace; use RuntimeException; use Laminas\ServiceManager\AbstractPluginManager; use Laminas\ServiceManager\Exception\InvalidServiceException; use Laminas\ServiceManager\Factory\InvokableFactory; class ObserverPluginManager extends AbstractPluginManager { protected $instanceOf = ObserverInterface::class; protected $aliases = [ 'mail' => MailObserver::class, 'Mail' => MailObserver::class, 'log' => LogObserver::class, 'Log' => LogObserver::class, ]; protected $factories = [ MailObserver::class => InvokableFactory::class, LogObserver::class => InvokableFactory::class, // Legacy (v2) due to alias resolution 'mynamespacemailobserver' => InvokableFactory::class, 'mynamespacelogobserver' => InvokableFactory::class, ]; protected $shareByDefault = false; protected $sharedByDefault = false; public function validate($instance) { if (! $instance instanceof $this->instanceOf) { throw new InvalidServiceException(sprintf( 'Invalid plugin "%s" created; not an instance of %s', get_class($instance), $this->instanceOf )); } } public function validatePlugin($instance) { try { $this->validate($instance); } catch (InvalidServiceException $e) { throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } } } ``` -------------------------------- ### Laminas Service Manager v2 Plugin Manager Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code defines a plugin manager for Laminas Service Manager version 2, including invokable services and plugin validation logic. ```php use RuntimeException; use Laminas\ServiceManager\AbstractPluginManager; class ObserverPluginManager extends AbstractPluginManager { protected $invokables = [ 'mail' => MailObserver::class, 'log' => LogObserver::class, ]; protected $shareByDefault = false; public function validatePlugin($instance) { if (! $instance instanceof ObserverInterface) { throw new RuntimeException(sprintf( 'Invalid plugin "%s" created; not an instance of %s', get_class($instance), ObserverInterface::class )); } } } ``` -------------------------------- ### Future-proofing Laminas Service Manager Initializer Callables Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Illustrates how to make a PHP callable used as an initializer in Laminas Service Manager forwards compatible with v3. This involves removing type hints and performing internal type checks to handle different argument orders. ```php $container->addInitializer(function ($instance, ContainerInterface $container) { if (! $instance implements FooAwareInterface) { return $instance; } $container->setFoo($services->get(FooInterface::class); return $instance; }); ``` ```php $container->addInitializer(function ($first, $second) { if ($first instanceof ContainerInterface) { $container = $first; $instance = $second; } else { $container = $second; $instance = $first; } if (! $instance implements FooAwareInterface) { return; } $container->setFoo($services->get(FooInterface::class); }); ``` -------------------------------- ### BuzzerDelegatorFactory Implementation in PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/delegators.md A concrete implementation of a delegator factory for the Buzzer service. It retrieves the real Buzzer instance via the callback, gets an EventManager from the container, attaches an event, and returns a new BuzzerDelegator. ```php use Interop\Container\ContainerInterface; use Laminas\ServiceManager\Factory\DelegatorFactoryInterface; class BuzzerDelegatorFactory implements DelegatorFactoryInterface { public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null) { $realBuzzer = call_user_func($callback); $eventManager = $container->get('EventManager'); $eventManager->attach('buzz', function () { echo "Stare at the art!\n"; }); return new BuzzerDelegator($realBuzzer, $eventManager); } } ``` -------------------------------- ### Add ReflectionBasedAbstractFactory in Laminas-MVC Application Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/reflection-abstract-factory.md This example shows how to integrate the ReflectionBasedAbstractFactory with custom mappings into a Laminas-MVC application's bootstrap process. It adds the factory to the service manager within the onBootstrap method of an Application module. ```php namespace Application; use Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory; class Module { public function onBootstrap($e) { $application = $e->getApplication(); $container = $application->getServiceManager(); $container->addAbstractFactory(new ReflectionBasedAbstractFactory([ /* ... mappings ... */ ])); } } ``` -------------------------------- ### v3 Service Manager Configuration with Lazy Services Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md This PHP code snippet demonstrates the updated configuration structure for Laminas Service Manager in version 3, including the new 'lazy_services' configuration for integrated lazy service loading. It shows required and optional settings for lazy services. ```php [ 'lazy_services' => [ // The class_map is required if using lazy services: 'class_map' => [ // service name => class name pairs ], // The following are optional: 'proxies_namespace' => 'Alternate namespace to use for generated proxy classes', 'proxies_target_dir' => 'path in which to write generated proxy classes', 'write_proxy_files' => true, // boolean; false by default ], ] ``` -------------------------------- ### Register ConfigAbstractFactory as a Mapped Factory (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/config-abstract-factory.md This example shows how to register the ConfigAbstractFactory as a mapped factory for a specific class within the service manager configuration. This allows it to be used for a particular service instead of as a general abstract factory. ```php return [ 'service_manager' => [ 'factories' => [ SomeCustomClass::class => ConfigAbstractFactory::class, ], ], ]; ``` -------------------------------- ### Laminas Service Manager v3 FactoryInterface Signature Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md The new signature of the FactoryInterface in Laminas Service Manager version 3, which uses the __invoke magic method and accepts a ContainerInterface, requested name, and optional options. ```php interface FactoryInterface { /** * Create an object * * @param ContainerInterface $container * @param string $requestedName * @param null|array $options * @return object */ public function __invoke(ContainerInterface $container, $requestedName, array $options = null); } ``` -------------------------------- ### PHP: Disable Sharing by Default Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/configuring-the-service-manager.md Demonstrates how to set the `shared_by_default` configuration option to `false` in the Service Manager. This makes all services, by default, non-shared, meaning `get()` will create new instances unless explicitly configured otherwise. ```php $serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class ], 'shared_by_default' => false, ]); $object1 = $serviceManager->get(stdClass::class); $object2 = $serviceManager->get(stdClass::class); var_dump($object1 === $object2); // prints "false" ``` -------------------------------- ### Define and Use Service Aliases in PHP Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/configuring-the-service-manager.md Demonstrates how to define aliases for services within the Laminas Service Manager configuration. Aliases provide alternative names for registered services and can be chained for recursive resolution. This example shows mapping 'A' to stdClass and 'B' to 'A'. ```php use Laminas\ServiceManager\Factory\InvokableFactory; use Laminas\ServiceManager\ServiceManager; use stdClass; $serviceManager = new ServiceManager([ 'factories' => [ stdClass::class => InvokableFactory::class ], 'aliases' => [ 'A' => stdClass::class, 'B' => 'A' ] ]); $object = $serviceManager->get('B'); ``` -------------------------------- ### AbstractPluginManager validate() Implementation Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/migration.md Provides a default implementation for the validate() method in AbstractPluginManager. It checks for a deprecated validatePlugin() method for backward compatibility, then verifies if the instance matches the expected type defined by $instanceOf. If validation fails, it throws an InvalidServiceException. ```php public function validate($instance) { if (method_exists($this, 'validatePlugin')) { trigger_error(sprintf( '%s::validatePlugin() has been deprecated as of 3.0; please define validate() instead', get_class($this) ), E_USER_DEPRECATED); $this->validatePlugin($instance); return; } if (empty($this->instanceOf) || $instance instanceof $this->instanceOf) { return; } throw new InvalidServiceException(sprintf( 'Plugin manager "%s" expected an instance of type "%s", but "%s" was received', __CLASS__, $this->instanceOf, is_object($instance) ? get_class($instance) : gettype($instance) )); } ``` -------------------------------- ### PHP: Manage Service Aliases and Factories in Laminas Service Manager Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/configuring-the-service-manager.md This example illustrates how to create an alias for a service and define a factory for another service within the Laminas Service Manager. It uses `setAlias()` to map one service name to another and `setFactory()` to define a callable factory. ```php // Create an alias from 'Date' to 'DateTime' $serviceManager->setAlias('Date', DateTime::class); // Set a factory for the 'Time' service $serviceManager->setFactory('Time', function ($container) { return $container->get(DateTime::class); }); ``` -------------------------------- ### PHP: Set Service Instances and Shared Flag in Laminas Service Manager Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v4/configuring-the-service-manager.md This example demonstrates how to explicitly set a service instance and control whether a service should be shared in the Laminas Service Manager. `setService()` is used to inject a pre-instantiated object, and `setShared()` controls the caching behavior of services. ```php // Explicitly map a service name to an instance. $serviceManager->setService('foo', new stdClass); // Mark the DateTime service as NOT being shared. $serviceManager->setShared(DateTime::class, false); ``` -------------------------------- ### Configure and use a plugin manager within ServiceManager (PHP) Source: https://github.com/laminas/laminas-servicemanager/blob/4.5.x/docs/book/v3/plugin-managers.md This PHP example shows how to configure a ValidatorPluginManager as a service within a parent ServiceManager. It includes a factory for the plugin manager itself and registers a StringLengthValidator with an InvokableFactory. The snippet then demonstrates retrieving the plugin manager and a specific validator from it. ```php $serviceManager = new ServiceManager([ 'factories' => [ ValidatorPluginManager::class => function(ContainerInterface $container, $requestedName) { return new ValidatorPluginManager($container, [ 'factories' => [ StringLengthValidator::class => InvokableFactory::class, ], ]); }, ], ]); // Get the plugin manager: $pluginManager = $serviceManager->get(ValidatorPluginManager::class); // Use the plugin manager $validator = $pluginManager->get(StringLengthValidator::class); ```