Hi everyone,
This is my first PR for ZF3. It is a direct backport of my PR on ZF2 repo.
Component is not yet fully tested but coverage should be already quite good.
Let me quickly recap the major changes of this refactor.
Motivation
The initial motivation was to dramatically increase the performance of this core component, while making it easier to use.
Performance wise, this refactor is dramatically faster, consume less memory (benchmark can be found on ZF2 repo).
Breaking changes
Removal of invokables
The concept of invokables no longer exist. Now, everything is a factory. This simplifies the creation code by having a single main way to create object.
A built-in factory to create invokables has been added.
ZF2 code:
return [
'invokables' => [
MyClass::class => MyClass::class
]
];
ZF3 code:
return [
'factories' => [
MyClass::class => InvokableFactory::class
]
]
Factories are invokables
To increase the performance and reduce branching, most interfaces (FactoryInterface, DelegatorFactory, AbstractFactory and Initializer) must be callable by implementing __invoke.
This offer a unified way to create objects and dramatically increase performance be removing a lot of instanceof checks.
Removal of aliases
Now that this component is 5.5+, we can take advantage of ::class, and we should encourage this usage.
The usage of aliases has been removed from the main service locator where ::class must be encouraged.
For plugin managers, a specialized plugin manager that supports alias has been introduced (AbstractAliasedPluginManager
) while a more efficient, alias-free AbstractPluginManager
is still here.
Ability to map multiple class to same factory
This was previously possible in ZF2 but in a hacky way. Now you can map multiple class names to the same factory, and it will be supported by default in the interface signature.
Plugin manager change
Previously, a plugin manager had a method getServiceLocator
to retrieve the main service locator.
This was confusing for new-comers, and could lead to hard to debug error because the constructor didn't neforce the need to pass a service locator as a dependency.
Now, what you receive in the factory is ALWAYS the main service manager, not the plugin manager one.
If you create an object through a plugin manager in ZF2 and want to retrieve a dependency in the main service locator you had to do:
class MyFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $sl)
{
$mainSl = $sl->getServiceLocator();
// ...
}
}
In ZF3:
class MyFactory implements FactoryInterface
{
public function __invoke(ServiceLocatorInterface $sl, $className, array $options = [])
{
// $sl is already the main service locator.
// If you want a dependency coming from the same plugin manager, you'll need to fetch it first
$pluginManager = $sl->get(MyPluginManager::class)
}
}
Unified way of having options
In ZF2 it was very hard to have options on factories. This is made easy now, because each interface have a last parameter called options.
Usage:
$object = $sl->get(MyObject::class, ['key' => 'value']);
// Options are passed as part of the options
Thanks