zend-phpdi-config acts as a bridge to configure a PSR-11 compatible PHP-DI container using service manager configuration. It can be used with Laminas and Mezzio starting from v6.0.0
This library uses autowiring technique, cache compilation and cache definitions as defined in PHP-DI.
To get a configured PSR-11 PHP-DI container, do the following:
<?php
use Elie\PHPDI\Config\Config;
use Elie\PHPDI\Config\ContainerFactory;
$factory = new ContainerFactory();
$container = $factory(
new Config([
'dependencies' => [
'services' => [],
'invokables' => [],
'autowires' => [], // A new key added to support PHP-DI autowire technique
'factories' => [],
'aliases' => [],
'delegators' => [],
],
// ... other configuration
// Enable compilation
Config::DI_CACHE_PATH => __DIR__, // Folder path
// Write proxies to file : cf. https://php-di.org/doc/lazy-injection.html
Config::DI_PROXY_PATH => __DIR__, // Folder path
// Disable autowire (enabled by default)
Config::USE_AUTOWIRE => false
// Enable cache
Config::ENABLE_CACHE_DEFINITION => false, // boolean, true if APCu is activated
])
);
The dependencies
sub associative array can contain the following keys:
services
: an associative array that maps a key to a specific service instance or service name.invokables
: an associative array that map a key to a constructor-less service; i.e., for services that do not require arguments to the constructor. The key and service name usually are the same; if they are not, the key is treated as an alias. It could also be an array of services.autowires
: an array of service with or without a constructor; PHP-DI offers an autowire technique that will scan the code and see what are the parameters needed in the constructors. Any aliases needed should be created in the aliases configuration.factories
: an associative array that maps a service name to a factory class name, or any callable. Factory classes must be instantiable without arguments, and callable once instantiated (i.e., implement the__invoke()
method).aliases
: an associative array that maps an alias to a service name (or another alias).delegators
: an associative array that maps service names to lists of delegator factory keys, see the Expressive delegators documentation for more details.
N.B.: The whole configuration -- unless
dependencies
-- is merged in aconfig
key within the$container
:$config = $container->get('config');
The cli command add-autowires-entry
creates the configuration file if it doesn't exist otherwise it adds the entry
to the autowires key.
Example of adding ConsoleHelper to a config.php:
./vendor/bin/add-autowires-entry config.php "Laminas\\Stdlib\\ConsoleHelper" [DONE] Changes written to config.php
Replace contents of config/container.php
with the following:
<?php
declare(strict_types = 1);
use Elie\PHPDI\Config\Config;
use Elie\PHPDI\Config\ContainerFactory;
// Protect variables from global scope
return call_user_func(function () {
$config = require __DIR__ . '/config.php';
$factory = new ContainerFactory();
// Container
return $factory(new Config($config));
});
<?php
class ConfigProvider
{
/**
* Returns the configuration array
*/
public function __invoke(): array
{
return [
'dependencies' => $this->getDependencies()
];
}
/**
* Returns the container dependencies
*/
public function getDependencies(): array
{
return [
'autowires' => [
UserManager::class
]
];
}
}
Where UserManager depends on Mailer as follow:
class UserManager
{
private $mailer;
public function __construct(Mailer $mailer)
{
$this->mailer = $mailer;
}
public function register($email, $password)
{
$this->mailer->mail($email, 'Hello and welcome!');
}
}
class Mailer
{
public function mail($recipient, $content)
{
}
}
To switch back to another container is very easy:
- Create your factories with
__invoke
function - Replace
autowires
key in ConfigProvider byfactories
key, then for each class name attach its correspondent factory.
V4.x supports as well Interop\Container\ContainerInterface
- Migration from 3.x to 4.0
- Migration from 4.x to 5.0: container-interop/container-interop was dropped in favor of PSR-11.