phpdependency-injectionconstructorcallbackphp-di

How is possible to execute a piece of code when an object is created in PHP-DI?


I set up my dependencies with \DI\Container like this:

$this->container = new \DI\Container();
$this->container->set('AdyenClient', \DI\create('\Adyen\Client'));
$this->container->set('AdyenCheckout', \DI\create('\Adyen\Service\Checkout')->constructor($this->container->get('AdyenClient')));

The \Adyen\Client cannot be configured in construction, so I need to execute a configClient() function, not associated in any way with the created object, after it's been created for the first time.

Is it possible to 'trigger' that method or any other piece of code the first time the object is being created by $this->container->get('AdyenClient'), even if it is needed to alter the way the dependencies are set up?

Nothing in the official documentation has a similar scenario as far as I read it.


Solution

  • With DI\create()

    You may use CreateDefinitionHelper::method to define method call when the object is created. Like this:

    $this->container = new \DI\Container();
    $this->container->set('AdyenClient',
      \DI\create('\Adyen\Client')->method('configClient', $param1, $param2));
    $this->container->set('AdyenCheckout',
      \DI\create('\Adyen\Service\Checkout')->constructor($this->container->get('AdyenClient')));
    

    PHP-DI will call AdyenClient::configClient with $param1 and $param2 after first created.

    With DI\factory()

    Alternatively, you may use the DI\factory function (which creates FactoryDefinitionHelper from a callback):

    $this->container = new \DI\Container();
    $this->container->set('AdyenClient',
      \DI\factory(function (Psr\Container\ContainerInterface $container) {
        $adyenClient = $container->get('\Adyen\Client');
        configClient($adyenClient);
        return $adyenClient;
      });
    $this->container->set('AdyenCheckout',
      \DI\create('\Adyen\Service\Checkout')->constructor($this->container->get('AdyenClient')));
    

    This should be a more flexible way to define any lazy-loaded thing in the container.