juliangut/slim-php-di

Slim Framework PHP-DI container integration

3.1.1 2020-02-13 22:04 UTC

This package is auto-updated.

Last update: 2020-02-13 22:21:45 UTC


README

PHP version Latest Version License

Build Status Style Check Code Quality Code Coverage

Total Downloads Monthly Downloads

Slim Framework PHP-DI container integration

PHP-DI (v6) dependency injection container integration for Slim framework.

Installation

Best way to install is using Composer:

composer require juliangut/slim-php-di

Then require_once the autoload file:

require_once './vendor/autoload.php';

Usage

Use Jgut\Slim\PHPDI\ContainerBuilder to create PHP-DI container and extract Slim's App from it

use App\ServiceOne;
use Jgut\Slim\PHPDI\Configuration;
use Jgut\Slim\PHPDI\ContainerBuilder;
use Psr\Container\ContainerInterface;
use Slim\App;

$settings = [
    'definitions' => '/path/to/definitions/files',
];
$container = ContainerBuilder::build(new Configuration($settings));

$app = $container->get(App::class);
// or $app = \Slim\Factory\AppFactory::createFromContainer($container);

// Register your services if not provided as definitions
$container->set('service_one', function (ContainerInterface $container) {
    return new ServiceOne($container->get('service_two'));
});

// Set your routes

$app->run();

In order to register services in the container it's way better to do it in definition files

Configuration

use Jgut\Slim\PHPDI\Configuration;

$settings = [
    'ignorePhpDocErrors' => true,
    'compilationPath' => '/path/to/compiled/container',
];
$configuration = new Configuration($settings);

// Can be set after configuration creation
$configuration->setProxiesPath(sys_get_temp_dir());
$configuration->setDefinitions('/path/to/definition/files');

$container = ContainerBuilder::build($configuration);

PHP-DI settings

  • useAutoWiring, whether or not to use auto wiring (true by default)
  • useAnnotations, whether or not to use annotations (false by default)
  • useDefinitionCache, whether or not to use definition cache (false by default)
  • ignorePhpDocErrors, whether or not to ignore phpDoc errors on annotations (false by default)
  • wrapContainer, wrapping container (none by default)
  • proxiesPath, path where PHP-DI creates its proxy files (none by default)
  • compilationPath, path to where PHP-DI creates its compiled container (none by default)

Refer to PHP-DI documentation to learn more about container configurations

In order for you to use annotations you have to require doctrine/annotations. See here

Additional settings

  • definitions, an array of paths to definition files/directories or arrays of definitions. Definitions are loaded in order of appearance
  • containerClass, container class that will be built. Must implement \Interop\Container\ContainerInterface, \DI\FactoryInterface and \DI\InvokerInterface (\Jgut\Slim\PHPDI\Container by default)

Array value access shorthand

Default \Jgut\Slim\PHPDI\Container container allows shorthand array values access by concatenating array keys with dots. If any key in the chain is not defined normal container's Psr\Container\NotFoundExceptionInterface is thrown

$container->get('configs')['database']['dsn']; // given configs is an array
$container->get('configs.database.dsn'); // same as above

Notice

Be careful though not to shadow any array key by using dots in keys itself

$configs = [
    'foo' => [
        'bar' => [
            'baz' => 'shadowed!',
        ],
    ],
    'foo.bar' => 'bang!',
];
$container->set('configs', $configs);

$container->get('configs.foo.bar'); // bang!
$container->get('configs.foo.bar.baz'); // NotFoundExceptionInterface thrown

The easiest way to avoid this from ever happening is by NOT using dots in array keys

Invocation strategy

By default slim-php-di sets a custom invocation strategy that employs PHP-DI's Invoker to fulfill callable parameters, it is quite handy and lets you do things like this

$app = $container->get(App::class);

$app->get('/hello/{name}', function (ResponseInterface $response, string $name, CustomDbConnection $connection): ResponseInterface {
    // $name will be injected from request arguments
    // $connection will be injected from the container

    $response->getBody()->write('Hello ' . $name);

    return $response;
});

$app->run();

If you prefer default Slim's Slim\Handlers\Strategies\RequestResponse strategy or any other of your choosing you only have to set it in a definition file

use Slim\Handlers\Strategies\RequestResponse;
use Slim\Interfaces\InvocationStrategyInterface;

use function DI\create;

return [
    InvocationStrategyInterface::class => create(RequestResponse::class),
];

Migration from 2.x

  • Minimum Slim version is now 4.2
  • Container only provides implementations of the interfaces needed to instantiate an App. Refer to Slim's documentation
  • You can extract Slim's App directly from container or seed AppFactory from container
  • Slim's App is not extended any more
  • ArrayAccess and magic methods on default container have been kept but are deprecated, use PSR-11 and PHP-DI's methods instead

Contributing

Found a bug or have a feature request? Please open a new issue. Have a look at existing issues before.

See file CONTRIBUTING.md

License

See file LICENSE included with the source code for a copy of the license terms.