laminas/laminas-servicemanager
Powerful dependency injection and service container for PHP. Manage factories, abstract factories, delegators, aliases, and shared services, with PSR-11 interoperability and robust configuration for complex applications.
Starting with version 3, Laminas\ServiceManager\Factory\AbstractFactoryInterface
extends Laminas\ServiceManager\Factory\FactoryInterface, meaning they may be used
as either an abstract factory, or mapped to a specific service name as its
factory.
As an example:
return [
'factories' => [
SomeService::class => AnAbstractFactory::class,
],
];
Why would you choose one approach over the other?
| Approach | Pros | Cons |
|---|---|---|
| Abstract factory | One-time setup | Performance; discovery of code responsible for creating instance |
| Factory | Performance; explicit mapping to factory responsible | Additional (duplicate) setup |
Essentially, it comes down to convenience versus explicitness and/or performance.
Writing a factory per service is time consuming, and, particularly in early stages of an application, can distract from the actual business of writing the classes and implementations; in addition, since requirements are often changing regularly, this boiler-plate code can be a nuisance.
In such situations, one or more abstract factories — such as the ConfigAbstractFactory, the ReflectionBasedAbstractFactory, or the laminas-mvc LazyControllerAbstractFactory — that can handle the bulk of your needs are often worthwhile, saving you time and effort as you code.
The drawback of abstract factories is that lookups by the service manager take longer, and increase based on the number of abstract factories in the system. The service manager is optimized to locate factories, as it can do an immediate hash table lookup; abstract factories involve:
This means, internally:
As such, having an explicit map can aid performance dramatically.
Additionally, having an explicit map can aid in understanding what class is responsible for initializing a given service. Without an explicit map, you need to identify all possible abstract factories, and determine which one is capable of handling the specific service; in some cases, multiple factories might be able to, which means you additionally need to know the order in which they will be queried.
The primary drawback is that you also end up with potentially duplicate information in your configuration:
ConfigAbstractFactory, additional configuration
detailing how to create the service.What it comes down to is which development aspects your organization or project favor. Hopefully the above arguments detail what tradeoffs occur, so you may make an appropriate choice.
Starting with 3.2.0, we began offering a variety of console tools to assist you in generating both dependency configuration and factories. Use these to help your code evolve. An expected workflow in your application development evolution is:
ReflectionBasedAbstractFactory as a "catch-all", so that you
do not need to do any factory/dependency configuration immediately.ConfigAbstractFactory, mapped to services, once dependencies
have settled, to disambiguate dependencies, or to list custom services
returning scalar or array values.generate-factory-for-class vendor binary to generate
actual factory classes for your production-ready code, providing the best
performance.How can I help you explore Laravel packages today?