Search code examples
phpdependency-injectionioc-containerphp-di

Referencing PHP-DI definitions defined as multi-dimensional arrays


If I have an array of definitions like below, the injection of a RouteCollector instance in other objects is executed perfectly:

use MyApp\Routing\RouteCollector;

return [
    'router.options.routeParser' => 'FastRoute\\RouteParser\\Std',
    'router.options.dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
    RouteCollector::class => DI\object()
            ->constructorParameter('routeParser', DI\get('router.options.routeParser'))
            ->constructorParameter('dataGenerator', DI\get('router.options.dataGenerator')),
];

But is there a way to achieve the same result if I define the router.options definition as array? E.g. how can I reference its elements in the RouteCollector::class definition?

use MyApp\Routing\RouteCollector;

return [
    'router.options' => [
        'routeParser' => 'FastRoute\\RouteParser\\Std',
        'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
    ],
    RouteCollector::class => DI\object()
            ->constructorParameter('routeParser', <ASKING>)
            ->constructorParameter('dataGenerator', <ASKING>),
];

Please note that it is not about passing the corresponding fully qualified class name (like \FastRoute\RouteParser\Std) as argument to the constructorParameter method. It's about referencing a config option defined in an array, in general.

Thank you for your support.


Solution

  • This is not possible out of the box. You could however do something like this (but it's not very readable):

    RouteCollector::class => DI\object()
            ->constructorParameter('routeParser', DI\factory(function ($c) {
                  return $c->get('router.options')['routeParser'];
              }))
    

    With the future v6.0 you will also be able to remove the DI\factory and directly put the closure.