phpdependency-injectionphp-di

php-di how to access container definitions


i have some config file which return array of key-value

return [
    'my_key' => 'my value',
];

i have added it to the php-di container as definition

$builder->addDefinitions(dirname(__DIR__) . '/config.php');
$container = $builder->build();

question is how to access data from the config file inside some method of the class which is used inside di container ?

lets say i have some classes

class App
{
    private $router;

    public function __construct(Router $router, Request $request)
    {
        $this->router = $router;
        $this->router->doSmth();
    }
}

class Router
{
    public function doSmth()
    {
       // how to access here to the config.php data to receive 'my value'
    }
}

so when i call

$container->get('\Core\App');

everything starts but i have no idea how to access the definitions data inside the methods of the registered classes because i dont have container instance inside the container itself to call smth like

$container->get('my_key'); // return 'my value'

Solution

  • In your App class __constructor the parameters are injected. Just like those, you can inject the configuration there.

    Your refer to the container by type hinting the ContainerInterface class. As mentioned in the issue on github your code for App will look like:

    class App
    {
        private $router;
    
        public function __construct(Router $router, Request $request, ContainerInterface $c)
        {
            $this->router = $router;
            $this->router->doSmth($c->get('my_key'));
        }
    }
    
    class Router
    {
        public function doSmth($my_key)
        {
           // You now have access to that particular key from the settings
        }
    }
    
    

    This will make your Router dependent on getting the config by the doSmth() function.


    Depending on your usage of the Router class, you might want to loose that dependency on calling doSmth($my_key) with that config parameter. Since in the App class you are injecting the Router class, it means you can also profit from injection in the Router class itself. Just like how you __construct your App class, you can also do that with your Router class.

    Doing this from the top of my head now, but this should work if I am not mistaken...

    Your code will look like this:

    class App
    {
        private $router;
    
        public function __construct(Router $router, Request $request)
        {
            $this->router = $router;
            $this->router->doSmth();
        }
    }
    
    class Router
    {
        private $some_setting;
    
        public function __construct(ContainerInterface $c)
        {
           $this->some_setting = $c->get('my_key');
        }
    
        public function doSmth()
        {
           // You now have access to $this->some_setting
        }
    }
    

    Note that the my_key key comes directly from the PHP-DI container definitions if for example a settings.php file with an array is added as definitions. More about definitions here. As I am combining this myself with the Slim framework, I usually prepend my keys in settings.php with settings. like for example setting.my_key. However there are probably cleaner solutions available if making use of the ability to extends definitions.