Daniel
Daniel

Reputation: 55

PHP-DI injectOn not injecting on setter methods

I have setup dependencies and definitions while configuring the container using the ContainerBuilder and then compiling it to get the actual Container, but whenever I try injecting dependencies they always tend to be ignored.

Have I missed the concept of the injectOn() method, or am I doing something wrong here ($this->translator remains unassigned)? I've tried different approaches to this, both instantiating the class and adding the object to the ContainerBuilder and also passing it as a \DI\object() definition, both with the same result.

<?php
include "../vendor/autoload.php";

class Translator
{}

class TextHandle
{
    protected $translator;

    public function setTranslator (Translator $translator)
    {
        $this->translator = $translator;
    }

    public function test ()
    {
        var_dump($this->translator);
    }
}

class TestCase
{
    protected $translator;

    public function __construct (Translator $translator)
    {
        $this->translator = $translator;
    }
}

// Setup container
$containerBuilder = new \DI\ContainerBuilder();
$containerBuilder->addDefinitions([
    Translator::class => \DI\object(),
]);

$container = $containerBuilder->build();

// Create object and inject
$textHandle = new TextHandle();
$container->injectOn($textHandle);

// Test injection, fails
$textHandle->test(); // NULL

// Test access, works
$translator = $container->get(Translator::class);
var_dump($translator); // object(Translator)#18 (0) {}

// Try having the container instantiate
$textHandle = $container->make(TextHandle::class);
$textHandle->test(); // Null

// Try object with constructor, works
$testCase = $container->make(TestCase::class);
var_dump($testCase); // Translator is set

Upvotes: 4

Views: 1154

Answers (2)

Zain Adi
Zain Adi

Reputation: 21

If you are using PHP 7.4, PHP DI 6.x

In fact you CAN inject dependency by using Property Injection or Setter Injection by using $container->injectOn($object)

Here's the detail.

  1. Add this line when you build the container: $builder->useAnnotation(true)
  2. Add doctrine/annotations v 1.x to your dependency: composer require doctrine/annotations:^1.14
  3. In your class, add this annotation before property or setter method:
/**
 * @Inject
 */
private NotificationServicesInterface $notificationServices;

AND / OR

private NotificationServicesInterface $notificationServices;

/**
 * @Inject
 */
public function setNotificationServices(NotificationServicesInterface $notificationServices) {
    $this->notificationServices = $notificationServices;
}

Note:

  • According to the documentation, https://php-di.org/doc/container.html#injecton, You should use make() or call() by default. Only use injectOn() only if you have to.
  • For PHP 8 or later you'll be using PHP DI 7, and you'll use PHP 8's attribute:
#[Inject]
private NotificationServicesInterface $notificationServices;
  • I havent tried PHP 8, but maybe you wouldn't need the doctrine/annotations anymore

Upvotes: 0

Bartosz Zasada
Bartosz Zasada

Reputation: 3900

According to the documentation, PHP-DI does not perform autowiring through setters.

You should add the definition for TextHandle class and configure it to inject Translator through the setter:

$containerBuilder->addDefinitions([
    TextHandle::class => \DI\object()->method('setTranslator', \DI\get(Translator::class))
]);

Upvotes: 4

Related Questions