elie29 / zend-di-config

PSR-11 PHP-DI container configurator for Laminas, Mezzio, ZF, Expressive applications or any framework that needs a PSR-11 container
MIT License
19 stars 4 forks source link
container expressive-composer-installer laminas mezzio mezzio-skeleton php-di php-di-container psr-11 zend-expressive zend-expressive-skeleton zend-framework zend-servicemanager

zend-phpdi-config

Build Status Coverage Status

Introduction

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.

Configuration

Service Manager Configuration

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:

N.B.: The whole configuration -- unless dependencies -- is merged in a config key within the $container:

$config = $container->get('config');

CLI command to add a new autowire entry

Configuration image

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

Using with Expressive

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));
});

Example of a ConfigProvider class

<?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)
    {
    }
}

Switching back to another container

To switch back to another container is very easy:

  1. Create your factories with __invoke function
  2. Replace autowires key in ConfigProvider by factories key, then for each class name attach its correspondent factory.

PSR 11 and Interop\Container\ContainerInterface

V4.x supports as well Interop\Container\ContainerInterface

Migration guides