2

For my PHP-DI container in a web MVC I prepared the following definition for a router:

return [
    'router' => function (ContainerInterface $c) {
        //...

        return new Router(...);
    }
];

Now I want to map an interface (MyLib\Routing\RouterInterface) to the implementation provided by the 'router' entry. In the PHP-DI documentation I found three ways of achieving this. Something like this:

  1. RouterInterface::class => DI\create('router')
  2. RouterInterface::class => DI\autowire('router')
  3. RouterInterface::class => DI\get('router')

When I applied the 3rd option, all were ok, e.g. I could retrieve the interface entry with:

$router = $container->get(RouterInterface::class);
var_dump($router);

But, when I tried the first two options, I received the error:

(1/1) InvalidDefinition

Entry "MyLib\Routing\RouterInterface" cannot be resolved: the class doesn't exist
Full definition:
Object (
class = #UNKNOWN# router
lazy = false
)

So I'd like to ask: Could you please explain to me, what is the difference between the three options in this case?

Thank you


Completion to the accepted answer:

The answer of @MatthieuNapoli is correct. I would though complete it with the following conclusion - based on a test I ran (see bellow).

Conclusion:

The helper functions create() and autowire() do not, in any way, reference an entry in the container. They receive a class name as argument and make sure that an object of that class is NEWLY created (once). This happens even if the name of an existing container definition is identical with the class name, and even if that entry already creates an object of the same type.

Solely the helper function get() references container entries, and not class names (as Matthieu already kindly presented).

Test:

1) I defined the following class:

<?php

namespace Test;

class MyTestClass {

    public function __construct($input = NULL) {
        if (empty($input)) {
            $input = 'NO INPUT';
        }

        echo 'Hello from MyTestClass. Input is: ' . $input . '<br/>';
    }

}

2) I defined the following container entries:

return [
    'Test\MyTestClass' => function (ContainerInterface $c) {
        return new Test\MyTestClass('12345');
    },
    'my.test.entry.for.create' => DI\create('Test\MyTestClass'),
    'my.test.entry.for.autowire' => DI\autowire('Test\MyTestClass'),
    'my.test.entry.for.get' => DI\get('Test\MyTestClass'),
];

3) I executed the following code:

<?php

$myTestEntryFor_MyTestClass = $container->get('Test\MyTestClass');

$myTestEntryFor_Create = $container->get('my.test.entry.for.create');
$myTestEntryFor_Autowire = $container->get('my.test.entry.for.autowire');

/*
 * This prints nothing, because an object of type "MyTestClass" was
 * already created by the container definition "'Test\MyTestClass'".
 */
$myTestEntryFor_Get = $container->get('my.test.entry.for.get');

4) I received the following results:

Hello from MyTestClass. Input is: 12345
Hello from MyTestClass. Input is: NO INPUT
Hello from MyTestClass. Input is: NO INPUT
PajuranCodes
  • 303
  • 3
  • 12
  • 43
  • http://php-di.org/doc/php-definitions.html#autowired-objects – Felippe Duarte Jul 27 '18 at 19:24
  • Thank you, @FelippeDuarte. I read the link. But why should I not use the option (3)? I mean, what is the difference between the options? – PajuranCodes Jul 27 '18 at 19:28
  • Hi, @FelippeDuarte. I received an answer and I accepted it too. Based on it I also ran a test. If you are still interested, at the end of my question I presented the conclusion. Thanks again and good luck. – PajuranCodes Jul 28 '18 at 21:37

1 Answers1

1

I invite you to check out the phpdoc of those functions in functions.php.

RouterInterface::class => DI\create('router')

That means create the router class: that PHP class doesn't exist.

RouterInterface::class => DI\autowire('router')

That means autowire the router class (which again doesn't exist).

RouterInterface::class => DI\get('router')

That means "when I ask for RouterInterface::class return the router entry. Notice that get() takes a container entry name, not a class name.

Matthieu Napoli
  • 48,448
  • 45
  • 173
  • 261
  • Hi, Matthieu. I ran a test and I also presented the conclusion of it at the end of my question. Please feel free to change it, or tell me to do it, if you think that is somewhat incorrect. Based on the examples on PHP-DI's web documention, at [Objects](http://php-di.org/doc/php-definitions.html#objects) and [Autowired objects](http://php-di.org/doc/php-definitions.html#autowired-objects), I permanently thought, that `create()` and `autowire()` would reference container definitions too. But I was wrong. Thanks again and best success further with your great project! – PajuranCodes Jul 28 '18 at 21:27