Open Menu

The Container#^ TOP

Internally, the workshop framework uses a dependency injection container. This allows you to request other services from the application and replace services with your own implementations. We use the PHP-DI package for dependency injection, a container-interop compatible dependency injection container.

Services are configured in app/config.php. You can use all of the features of PHP-DI so check the docs there.

The file app/config.php should return an array of service definitions for the container. The key being the name of the service and the value the actual factory.

Defining Factories#^ TOP

Simple Object with No dependencies

\DI\Object() is a helper function to create a factory which will simply run new $yourClassName when asking for the service from the container.

return [
    ...snip
    Generator::class => \DI\Object(),
];

Object with dependencies

PHP-DI provides more powerful features such as being able to use anonymous functions and any valid PHP callables as a factory. When using a callable your callable will be injected with the container itself which you can pull other services from!

If you pulled in a third party library for random number generation you might define a service like below. We use the battle tested package: ircmaxell/random-lib as an example.

We use an anonymous function and pull the strength parameter from the container and create a new random number generator based on that.

return [
    ...snip
    \RandomLib\Generator::class => \DI\factory(function (ContainerInterface $container) {
        $strength = $container->get('random-number-generator-strength');
        $factory = new \RandomLib\Factory;
        return $factory->getGenerator(new \SecurityLib\Strength($strength));
    }),
];

Overwriting existing services#^ TOP

As your workshop configuration is merged into default workshop framework configuration, you can override existing services with your own implementation. Maybe you want to override the \Symfony\Component\Filesystem\Filesystem service with your own version, maybe you extended it to add some methods.

The below definition would replace the Symfony\Component\Filesystem\Filesystem service with your own implementation: MyFileSystem which extends from \Symfony\Component\Filesystem\Filesystem.

return [
    ...snip
    Symfony\Component\Filesystem\Filesystem::class => \DI\factory(function (ContainerInterface $c) {
        return new MyFileSystem;
    }),
];

Now when you ask the container for Symfony\Component\Filesystem\Filesystem you will receive an instance of MyFileSystem.

Be aware that anything already using the Symfony\Component\Filesystem\Filesystem service will expect it to be an instance of \Symfony\Component\Filesystem\Filesystem, so if you replace it with an altogether different object, expect things to break!

Check Available Services for a list and description of services available to you.