# \[RFC\] Removal of container-interop from laminas-servicemanager

**URL:** <https://discourse.laminas.dev/t/rfc-removal-of-container-interop-from-laminas-servicemanager/1608>\
**Category:** Contributors\
**Tags:** laminas-servicemanager\
**Created:** [May 14, 2020, 4:54pm UTC](https://discourse.laminas.dev/t/rfc-removal-of-container-interop-from-laminas-servicemanager/1608 "2020-05-14T16:54:19Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![matthew](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/matthew/32/14_2.png) [@matthew](https://discourse.laminas.dev/u/matthew)\
**Post date:** [May 14, 2020, 4:54pm UTC](https://discourse.laminas.dev/t/rfc-removal-of-container-interop-from-laminas-servicemanager/1608/1 "2020-05-14T16:54:19Z")

</div>

## Background

Currently, laminas-servicemanager depends on container-interop/container-interop. This is because we were part of the working group for PSR-11, and chose to adapt our code to it before the specification stabilized and was accepted. Once it was, container-interop modified its interfaces such that they now extend the PSR-11 interfaces, and thus can be used anywhere PSR-11 is.

However, ultimately this means that we cannot update directly to PSR-11 without a backwards compatilibity break, as a number of our interfaces and implementations directly typehint against the container-interop interfaces still, and doing so would break userland implementations and extensions.

## Plan for removal

We will create a new package, something along the line of “laminas/laminas-container-contracts”, which would ship the various factory interfaces (and some utility classes implementing them) currently in laminas-servicemanager, but targeting PSR-11 instead. These include the following interfaces:

- `Laminas\ServiceManager\Factory\AbstractFactoryInterface`
- `Laminas\ServiceManager\Factory\DelegatorFactoryInterface`
- `Laminas\ServiceManager\Factory\FactoryInterface`
- `Laminas\ServiceManager\Initializer\InitializerInterface` (this one is up for debate, as we are largely directing users towards delegators instead)

and the following implementations:

- `Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory` (uses reflection to create an instance of the class requested).
- `Laminas\ServiceManager\Factory\InvokableFactory` (creates an instance of a class using `new` and no constructor arguments)

laminas-servicemanager would be updated such that the `ServiceManager` could consume both implementations of its own interfaces, as well as those from the new package. This allows users and other packages to adopt the PSR-11 variants immediately in order to remain forwards-compatible with version 4. Additionally, since such checks generally happen during configuration, and not runtime, they should have little to any performance impact.

Existing interfaces and implementations with equivalents in the new package would be marked `@deprecated`.

For implementations we provide within laminas-servicemanager, if the class is marked `final`, we would update it to use the PSR-11 interfaces; this affects the `ConfigAbstractFactory` and `InvokableFactory` only at this time. Otherwise, in the documentation, we would point users to the new interfaces package.

Finally, we will provide laminas-cli commands to allow users to:

- Identify implementations of the legacy interfaces in their own code.
- Identify usage of legacy implementations in configuration, and update them.
- Potentially update legacy implementations to implement the new interfaces (this might not be viable, however).

In version 4, we would remove the legacy definitions and implementations entirely, and update the `ServiceManager` to only typehint against the new versions.

## Packages implementing or consuming laminas-servicemanager interfaces

When it comes to packages that implement or consume laminas-servicemanager interfaces, modifying non-final classes that implement the current interfaces would clearly be a backwards-compatibility break. As such, the plan would be:

- Deprecate the existing implementations.
- Ship parallel implementations targeting the new interfaces.
- Document the new implementations.
- If the package provides autowiring via a `ConfigProvider` or `Module` class, only reference the new implementations.

Since user extensions would have to be wired manually anyways, such extensions would continue to work.

### Components with implementations

What follows is a list of components that have implementations of laminas-servicemanager interfaces. With each, I have listed whether or not autowiring is present in the package, and then each implementation, including information on:

- its purpose
- what it implements
- whether or not it is autoregistered

In the majority of cases, we can do the following:

- Add a dependency on the new contracts package.
- Create parallel implementations targeting the contracts package.
- Deprecate the original implementations.
- Use the new implementations in any autowiring present.
- Make laminas-servicemanager and/or container-interop _suggested_ packages instead of _require_ packages.
- Document the new classes, and note that users of the legacy implementations will need to migrate to the new implementations (either by changing configuration or changing inheritance trees).

### Affected Components

> **List of affected components (click to expand)**
>
> - **laminas/laminas-cache**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `PatternPluginManagerFactory` (create pattern plugin instances; `FactoryInterface` implementation; registered)
> - `StorageAdapterPluginManagerFactory` (create adapter plugin manager instance; `FactoryInterface` implementation; registered)
> - `StorageCacheAbstractServiceFactory` (create named `StorageInterface` instances; `AbstractFactoryInterface` implementation; registered)
> - `StorageCacheFactory` (create default `StorageInterface` instance; `FactoryInterface` implementation; **NOT registered** )
> - `StoragePluginManagerFactory` (return `PluginManager` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-config**
> - Package **DOES NOT** have a `ConfigProvider` or `Module` class
> - `AbstractConfigFactory` (pluck config segments from the `config` service; `AbstractFactoryInterface` implementation)
> 
> - **laminas/laminas-db**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `AdapterAbstractServiceFactory` (provide named DB adapters; `AbstractFactoryInterface` implementation; registered)
> - `AdapterServiceFactory` (provide default DB adapter; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-di**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `AutowireFactory` (DI autowiring; `AbstractFactoryInterface` implementation; registered)
> 
> - **laminas/laminas-filter**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `FilterPluginManagerFactory` (creates `FilterPluginManager` instance; `FactoryInterface` implementation; registered)
> - `SeparatorToSeparatorFactory` (creates `SeparatorToSeparator` instances based on `$options` provided; `FactoryInterface` implementation; registered in `FilterPluginManager` instance)
> 
> - **laminas/laminas-form**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `AnnotationBuilderFactory` (create and return `AnnotationBuilder` instance; `FactoryInterface` implementation; registered)
> - `ElementFactory` (create and return `ElementInterface` implementations, using `$options`; `FactoryInterface` implementation; registered by `FormElementManager`; **IS FINAL** )
> - `FormAbstractServiceFactory` (create and return `FormInterface` instances; `AbstractFactoryInterface` implementation; registered)
> - `FormElementManagerFactory` (create and return `FormElementManager` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-i18n**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `LoaderPluginManagerFactory` (create and return `LoaderPluginManager` instance; `FactoryInterface` implemenation; registered)
> - `TranslatorServiceFactory` (create and return `Translator` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-inputfilter**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `InputFilterAbstractServiceFactory` (produces named `InputFilterInterface` instances; `AbstractFactoryInterface` implementation; registered with `InputFilterPluginManager` **and in laminas-api-tools/api-tools-content-validation** )
> - `InputFilterPluginManagerFactory` (produces `InputFilterPluginManager` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-log**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `FilterPluginManagerFactory` (produces `FilterPluginManager` instance; `FactoryInterface` implementation; registered)
> - `FormatterPluginManagerFactory` (produces `FormatterPluginManager` instance; `FactoryInterface` implementation; registered)
> - `LoggerAbstractServiceFactory` (produces named `Logger` instances; `AbstractFactoryInterface` implementation; registered)
> - `LoggerServiceFactory` (produces default `Logger` instance; `FactoryInterface` implementation; registered)
> - `ProcessorPluginManagerFactory` (produces `ProcessorPluginManager` instance; `FactoryInterface` implementation; registered)
> - `WriterFactory` (produces `WriterInterface` instances using provided name and options; `FactoryInterface` implementation; registered in `WriterPluginManager`)
> - `WriterPluginManagerFactory` (produces `WriterPluginManager` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-mail**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `SmtpPluginManagerFactory` (produces `SmtpPluginManager` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-mvc**
> - Package **DOES NOT** have either a `ConfigProvider` or a `Module` class (but there are some proposals to add them in a development version)
> - `LazyControllerAbstractFactory` (reflection-based factory for producing controllers; `AbstractFactoryInterface` implementation; **NOT registered** anywhere — completely optional)
> - `ForwardFactory` (produces a `Forward` plugin instance; `FactoryInterface` implementation; registered in `ControllerManager`)
> - `AbstractPluginManagerFactory` (abstract class for plugin manager factories; `FactoryInterface` implementation, providing the `__invoke()` definition).
> - `ApplicationFactory` (produces an `Application` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ConfigFactory` (produces the `config` service by retrieving the ModuleManager, loading modules, retrieving the configuration listener, and pulling the config it aggregates; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ControllerManagerFactory` (produces a `ControllerManager` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `DispatchListenerFactory` (produces a `DispatchListener` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `EventManagerFactory` (produces an `EventManager` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `HttpDefaultRenderingStrategyFactory` (produces a `View\Http\DefaultRenderingStrategy` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `HttpExceptionStrategyFactory` (produces an `Http\ExceptionStrategy` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `HttpMethodListenerFactory` (produces an `HttpMethodListener` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `HttpRouteNotFoundStrategyFactory` (produces a `View\Http\RouteNotFoundStrategy` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `HttpViewManagerFactory` (produces a `View\Http\ViewManager` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `InjectTemplateListenerFactory` (produces a `View\Http\InjectTemplateListener` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ModuleManagerFactory` (produces a `ModuleManager` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `RequestFactory` (produces a `Request` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ResponseFactory` (produces a `Response` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ServiceListenerFactory` (produces a `ServiceListener` instance; `FactoryInterface` implementation; registered in skeleton)
> - `ViewFactory` (produces a `View` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewFeedStrategyFactory` (produces a `ViewFeedStrategy` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewJsonStrategyFactory` (produces a `ViewJsonStrategy` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewManagerFactory` (produces a `ViewManager` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewPhpRendererFactory` (produces a `ViewPhpRenderer` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewPhpRendererStrategyFactory` (produces a `ViewPhpRendererStrategy` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewPrefixPathStackResolverFactory` (produces a `ViewPrefixPathStackResolver` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewResolverFactory` (produces a `ViewResolver` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewTemplateMapResolverFactory` (produces a `ViewTemplateMapResolver` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> - `ViewTemplatePathStackResolverFactory` (produces a `ViewTemplatePathStackResolver` instance; `FactoryInterface` implementation; registered in `ServiceListenerFactory`)
> 
> - **laminas/laminas-mvc-console**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `ConsoleRouterDelegatorFactory` (substitutes console router for HTTP router if console env detected; `DelegatorFactoryInterface` implementation; registered)
> - `ConsoleRouterFactory` (produces console router instance; `FactoryInterface` implementation; registered)
> - `SimpleRouteStack` **(consumes laminas-router `RouteInvokableFactory`, `RoutePluginManager`, `SimpleRouteStack`)**
> - `ConsoleAdapterFactory` (produces console instance; `FactoryInterface` implementation; registered)
> - `ConsoleApplicationDelegatorFactory` (attaches an alternate view renderer to the laminas-mvc `Application` instance; `DelegatorFactoryInterface` implementation; **NOT** registered, and, in fact, deprecated)
> - `ConsoleExceptionStrategyFactory` (produces a console `ExceptionStrategy`; `FactoryInterface` implementation, registered)
> - `ConsoleRequestDelegatorFactory` (substitutes console request for HTTP request if console env detected; `DelegatorFactoryInterface` implementation; registered)
> - `ConsoleResponseDelegatorFactory` (substitutes console response for HTTP response if console env detected; `DelegatorFactoryInterface` implementation; registered)
> - `ConsoleResponseSenderDelegatorFactory` (injects console response sender in send response listener; `DelegatorFactoryInterface` implementation; registered)
> - `ConsoleRouteNotFoundStrategyFactory` (produces `RouteNotFoundStrategy` instance; `FactoryInterface` implementation; registered)
> - `ConsoleViewHelperManagerDelegatorFactory` (injects alternative url, basepath, and server url plugins in view helper manager if console env detected; `DelegatorFactoryInterface` implementation; registered)
> - `ConsoleViewManagerFactory` (produces `ConsoleViewManager` instance; `FactoryInterface` implementation; registered)
> - `ControllerManagerDelegatorFactory` (injects initializer into `ControllerManager` for injecting console instance into controllers; `DelegatorFactoryInterface` implementation; registered)
> - `DefaultRenderingStrategyFactory` (produces `DefaultRenderingStrategy` instance; `FactoryInterface` implementation; registered)
> - `ViewManagerDelegatorFactory` (replaces HTTP view manager with Console view manager instance; `DelegatorFactoryInterface` implementation; registered)
> 
> - **laminas/laminas-mvc-i18n**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `HttpRouterDelegatorFactory` (injects router with `Translator` instance if it is available and the router supports translation; `DelegatorFactoryInterface` implementation; registered)
> - `TranslatorFactory` (produces `Translator` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-mvc-plugin-flashmessenger**
> - Package **DOES** have a `Module` class
> - `FlashMessengerFactory` (produces `FlashMessenger` view helper instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-mvc-plugin-identity**
> - Package **DOES** have a `Module` class
> - `IdentityFactory` (produces `Identity` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-navigation**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `AbstractNavigationFactory` ( **abstract class** produces a `Navigation` instance; `FactoryInterface` implementation)
> - `NavigationAbstractServiceFactory` (produces named `Navigation` instances; `AbstractFactoryInterface` implementation; registered)
> - `NavigationHelperFactory` (produces `Navigation` view helper instance; `FactoryInterface` implementation; registered in `HelperConfig`
> - `ViewHelperManagerDelegatorFactory` (injects view helper manager with `HelperConfig`; `DelegatorFactoryInterface` implementation; registered)
> 
> - **laminas/laminas-paginator**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `AdapterPluginManagerFactory` (produces `AdapterPluginManager` instance; `FactoryInterface` implementation; registered)
> - `CallbackFactory` (produces `Callback` adapter instance; `FactoryInterface` implementation; registered in `AdapterPluginManager`)
> - `DbSelectFactory` (produces `DbSelect` adapter instance; `FactoryInterface` implementation; registered in `AdapterPluginManager`)
> - `DbTableGatewayFactory` (produces `DbTableGateway` adapter instance; `FactoryInterface` implementation; registered in `AdapterPluginManager`)
> - `IteratorFactory` (produces `Iterator` adapter instance; `FactoryInterface` implementation; registered in `AdapterPluginManager`)
> - `ScrollingStylePluginManagerFactory` (produces `ScrollingStylePluginManager` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-router**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `HttpRouterFactory` (produces a `TreeRouteStack` instance; `FactoryInterface` implementation; registered)
> - `TreeRouteStack` (consumes `RouteInvokableFactory`)
> - `RouteInvokableFactory` (produces `RouteInterface` instances; `FactoryInterface` **and** `AbstractFactoryInterface` implementation)
> - `RoutePluginManagerFactory` (produces `RoutePluginManager` instance; `FactoryInterface` implementation; registered)
> - `RoutePluginManager` (consumes `RouteInvokableFactory` as an abstract factory; registered)
> - `RouterFactory` (produces `RouteStackInterface` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-serializer**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `AdapterPluginManagerFactory` (produces an `AdapterPluginManager` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-servicemanager-di**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `DiAbstractServiceFactoryFactory` (produces `DiAbstractServiceFactory` instance; `FactoryInterface` implementation; registered)
> - `DiAbstractServiceFactory` (produces arbitrary instances based on reflection; `AbstractFactoryInterface` implementation, **not registered** )
> - `DiFactory` (produces `Laminas\Di\Di` instance; `FactoryInterface` implementation; registered)
> - `DiServiceFactory` (produces arbitrary instances based on reflection; `FactoryInterface` implementation; **not registered** )
> - `DiServiceInitializerFactory` (produces `DiServiceInitializer` instance; `FactoryInterface` implementation; registered)
> - `DiStrictAbstractServiceFactoryFactory` (produces `DiStrictAbstractServiceFactory` instance; `FactoryInterface` implementation; registered)
> - `DiStrictAbstractServiceFactory` (produces arbitrary instances based on reflection; `AbstractFactoryInterface` implementation, **not registered** )
> 
> - **laminas/laminas-session**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `ContainerAbstractServiceFactory` (produces session `Container` instances; `AbstractFactoryInterface` implementation; registered)
> - `SessionConfigFactory` (produces appropriate session `ConfigInterface` instance; `FactoryInterface`implementation; registered)
> - `SessionManagerFactory` (produces `SessionManagerInterface` instance; `FactoryInterface` implementation; registered)
> - `StorageFactory` (produces `StorageInterface` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-validator**
> - Package **DOES** have both a `ConfigProvider` and a `Module` class
> - `ValidatorPluginManagerFactory` (produces `ValidatorPluginManager` instance; `FactoryInterface` implementation; registered)
> 
> - **laminas/laminas-view**
> - Package **DOES NOT** have either a `ConfigProvider` or a `Module` class
> - `AssetFactory` (produces `Asset` view helper instance; `FactoryInterface` implementation; registered with `HelperPluginManager)
> - `FlashMessengerFactory` (produces `FlashMessenger` view helper instance; `FactoryInterface` implementation; registered with `HelperPluginManager)
> - `IdentityFactory` (produces `Identity` view helper instance; `FactoryInterface` implementation; registered with `HelperPluginManager)
> 
> - **laminas-api-tools/api-tools**
> - Package has a `Module` class backed by a `module.config.php` file
> - `TableGatewayAbstractFactory` (produces named TDG instances; `AbstractFactoryInterface` implementation; registered in `module.config.php`)
> - `DbConnectedResourceAbstractFactory` (produces `Laminas\ApiTools\Rest\Resource` instances; `AbstractFactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-admin**
> - Package has a `Module` class backed by a `module.config.php` file
> - `AuthenticationControllerFactory` (produces `AuthenticationController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `AuthenticationTypeControllerFactory` (produces `AuthenticationTypeController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `AuthorizationControllerFactory` (produces `AuthorizationController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `ConfigControllerFactory` (produces `ConfigController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `DashboardControllerFactory` (produces `DashboardController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `DbAutodiscoveryControllerFactory` (produces `DbAutodiscoveryController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `DocumentationControllerFactory` (produces `DocumentationController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `FiltersControllerFactory` (produces `FiltersController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `HydratorsControllerFactory` (produces `HydratorsController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `InputFilterControllerFactory` (produces `InputFilterController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `ModuleConfigControllerFactory` (produces `ModuleConfigController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `ModuleCreationControllerFactory` (produces `ModuleCreationController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `SourceControllerFactory` (produces `SourceController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `StrategyControllerFactory` (produces `StrategyController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `ValidatorsControllerFactory` (produces `ValidatorsController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `VersioningControllerFactory` (produces `VersioningController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `InputFilterInputFilterFactory` (produces `InputFilterInputFilter` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `AbstractPluginManagerModelFactory` (produces `AbstractPluginManagerModel` instance; `FactoryInterface` implementation; **extended by `HydratorsModelFactory`** , which is registered)
> - `DocumentationModelFactory` (produces `DocumentationModel` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `FiltersModelFactory` (produces `FiltersModel` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `InputFilterModelFactory` (produces `InputFilterModel` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `ValidatorMetadataModelFactory` (produces `ValidatorMetadataModel` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `ValidatorsModelFactory` (produces `ValidatorsModel` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-content-negotiation**
> - Package has a `Module` class backed by a `module.config.php` file
> - `RenameUploadFilterFactory` (produces `RenameUpload` filter instance; `FactoryInterface` implementation; registered in `module.config.php`
> - `UploadFileValidatorFactory` (produces `UploadFile` validator instance; `FactoryInterface` implementation; registered in `module.config.php`
> - `module.config.php` (registers laminas-db `AdapterAbstractServiceFactory`)
> 
> - **laminas-api-tools/api-tools-content-validation**
> - Package has a `Module` class backed by a `module.config.php` file
> - `ContentValidationListenerFactory` (produces `ContentValidationListener` instance; `FactoryInterface` implementation; registered in `module.config.php`
> - `NoRecordExistsFactory` (produces `NoRecordExists` validator; `FactoryInterface` implementation; registered in `module.config.php`)
> - `RecordExistsFactory` (produces `RecordExists` validator; `FactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-doctrine**
> - Package has a `Module` class backed by a `server.config.php` and an `admin.config.php` file
> - `DoctrineAutodiscoveryControllerFactory` (produces `DoctrineAutodiscoveryController` instance; `FactoryInterface` implementation; registered in `admin.config.php`)
> - `DoctrineResourceFactory` (produces `DoctrineResource` instances; `AbstractFactoryInterface` implementation; registered in `server.config.php`)
> - `NoObjectExistsFactory` (produces `NoObjectExists` instance; `FactoryInterface` implementation; registered in `server.config.php`)
> - `ObjectExistsFactory` (produces `ObjectExists` instance; `FactoryInterface` implementation; registered in `server.config.php`)
> 
> - **laminas-api-tools/api-tools-documentation**
> - Package has a `Module` class backed by a `module.config.php` file
> - `ControllerFactory` (produces `Controller` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-documentation-apiblueprint**
> - Package has a `Module` class backed by a `module.config.php` file
> - `ControllerFactory` (produces `Controller` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-documentation-swagger**
> - Package has a `Module` class backed by a `module.config.php` file
> - `SwaggerUiControllerFactory` (produces `SwaggerUiController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-hal**
> - Package has a `Module` class backed by a `module.config.php` file
> - `HalControllerPluginFactory` (produces `Hal` plugin; `FactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-mvc-auth**
> - Package has a `Module` class backed by a `module.config.php` file
> - `AclAuthorizationFactory` (produces `AclAuthorization` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `ApacheResolverFactory` (produces `ApacheResolver` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `AuthenticationAdapterDelegatorFactory` (injects adapters into `DefaultAuthenticationListener`; `DelegatorFactoryInterface` implementation; registered in `module.config.php`)
> - `AuthenticationServiceFactory` (produces `Laminas\Authentication\AuthenticationService` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `DefaultAuthenticationListenerFactory` (produces `DefaultAuthenticationListener` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `DefaultAuthHttpAdapterFactory` (produces `Laminas\Authentication\Adapter\Http` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `DefaultAuthorizationListenerFactory` (produces `DefaultAuthorizationListener` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `DefaultResourceResolverListenerFactory` (produces `DefaultResourceResolverListener` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `FileResolverFactory` (produces `FileResolver` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-oauth2**
> - Package has a `Module` class backed by a `module.config.php` file
> - `AuthControllerFactory` (produces `AuthController` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-rest**
> - Package has a `Module` class backed by a `module.config.php` file
> - `OptionsListenerFactory` (produces `OptionsListener` instance; `FactoryInterface` implementation; registered in `module.config.php`)
> - `RestControllerFactory` (produces `RestController` instances; `AbstractFactoryInterface` implementation; registered in `module.config.php`)
> 
> - **laminas-api-tools/api-tools-rpc**
> - Package has a `Module` class backed by a `module.config.php` file
> - `RpcControllerFactory` (produces `RpcController` instances; `AbstractFactoryInterface` implementation; registered in `module.config.php`)

---

<div class="post-metadata">

**Author:** ![boesing](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/boesing/32/832_2.png) [@boesing](https://discourse.laminas.dev/u/boesing)\
**Post date:** [November 19, 2020, 7:56pm UTC](https://discourse.laminas.dev/t/rfc-removal-of-container-interop-from-laminas-servicemanager/1608/3 "2020-11-19T19:56:37Z")

</div>

First of all, this is a great addition. As we have the chance to totally re-work the whole ServiceManager ecosystem, I’d like to propose some more changes for the upcoming v4.

What about having new interfaces for `PluginManager` instances only? Imho, the only reason when I consume `options` within a factory is, when I am working with Plugins.

When we are splitting interfaces, it can be easier to create new stuff for plugin managers and we can finally have some return typehints (such as `object` for all plugin factories) aswell as providing generics for those factories as every factory within a specific plugin manager have to return a specific implementation of a pre-defined instance.

## PluginManager factory interfaces

### PluginFactoryInterface

Provides a method `PluginFactoryInterface::__invoke(ContainerInterface $container, array $options): object`

### AbstractPluginFactoryInterface

Provides the well-known `AbstractPluginFactoryInterface:canCreate(ContainerInterface $container, string $requestedName): bool` method aswell as `AbstractPluginFactoryInterface::__invoke(ContainerInterface $container, string $requestedName, array $options): object`

### PluginDelegatorFactoryInterface

Provides `PluginDelegatorFactoryInterface::__invoke(ContainerInterface $container, callable $factory, array $options): object`

I’d omitted the `$name` parameter from the `PluginDelegatorFactoryInterface` as I think that most of the time, `instanceof` is being used on the return value of the `$factory`-callable anyways.

## ServiceManager factory interfaces

### FactoryInterface

Imho, this can be dropped at all. There is no need for that interface as 99,99% of factories I’ve seen in the wild are neither using `$requestedName` nor `$options` at all.  
As the `InvokableFactory` is a special factory, it could be changed to something like this:

```php
/**
 * @template T of object
 */ 
final class InvokableFactory
{
    /**
     * @psalm-var class-string<T>
     */
    private $invokableClass;

    /**
     * @psalm-param class-string<T> $invokableClass
     */
    public function __construct(string $invokableClass)
    {
        $this->invokableClass = $invokableClass;
    }

    /**
     * @psalm-return T
     */
    public function __invoke(ContainerInterface $container): object
    {
        $invokable = $this->invokableClass;
        return new $invokable;
    }
}

```

It can be instantiated from within the servicemanager and/or custom implementations  
_We could also create an invokable factory for plugins to avoid having an all-in-one implementation here aswell_

### InitializerInterface

I am +1 for removal of anything regarding initializers as they’re executed on every service and thus every initializer has direct performance implications on _every_ service within the service manager.

### ReflectionBasedAbstractFactory

I’d prefer not using this factory in any project (due to performance) but as there is no other “handy” way of creating factories for “simple services”, I see why this is still part of the library.  
Same suggestion here: we might create one for plugins and one for “services”.

## Summary

When we split-up factories between `PluginManager` and `ServiceManager`, we can provide better interfaces (especially for plugins) and avoid confusion regarding the meaning of the `options` parameter which is almost always `null`.

I’d propose to drop the `ServiceLocatorInterface` with this aswell, as projects should not rely on the servicemanager implementation but on the PSR-11 interface. All these changes might require a new major version bump and thus, old factory interfaces might be dropped and therefore there is no need to use the `ServiceLocatorInterface` anymore.

This said, we could remove `ServiceManager::build` which then means, that there is a 100% chance that `options` is always `null`.

Instead, we might want to have a `PluginManagerInterface` (which extends the `ContainerInterface`) with the `PluginManager::build` method instead.

Thus, the `AbstractPluginManager` will implement that new interface, the `build`-Method and so on.

Thoughts?

---

<div class="post-metadata">

**Author:** ![internalsystemerror](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/internalsystemerror/32/962_2.png) [@internalsystemerror](https://discourse.laminas.dev/u/internalsystemerror)\
**Post date:** [April 27, 2021, 12:36pm UTC](https://discourse.laminas.dev/t/rfc-removal-of-container-interop-from-laminas-servicemanager/1608/4 "2021-04-27T12:36:27Z")

</div>

We’re using the $requestedName quite extensively as this allows us to reuse factories, and to retrieve an interface in the lib which is aliased to a particular class via configuration in the app. (If DI would be a better solution for us here to reduce boilerplate, then I’m happy to move to that and accept the deprecation)

As an aside, I’m also curious how this would affect all other laminas/mezzio components based on this. My assumption is that once SM4 does get released, each framework component will also need a BC break for the factories that are not final? Or would these be considered internal?

Either way happy for BC breaks, looking forward to v4.
