PHP-DI:创建vs.自动装配vs.获取。或如何将接口正确映射到定义提供的实现

时间:2018-07-27 19:15:27

标签: php php-di

对于Web MVC中的PHP-DI容器,我为路由器准备了以下定义:

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

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

现在,我想将接口(MyLib\Routing\RouterInterface)映射到'router'条目提供的实现。在PHP-DI文档中,我找到了实现此目的的三种方法。像这样:

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

当我应用第三个选项时,一切都很好,例如我可以使用以下方式检索接口条目:

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

但是,当我尝试前两个选项时,我收到了错误消息:

(1/1) InvalidDefinition

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

所以我想问:您能否向我解释一下,在这种情况下这三种选择之间有什么区别?

谢谢


完成接受的答案:

@MatthieuNapoli的答案是正确的。我会用以下结论来完成它-基于我运行的测试(请参见下面的内容)。

结论:

辅助函数create()autowire()不会以任何方式引用容器中的条目。他们收到一个类名作为参数,并确保(一次)创建该类的对象 NEWLY 。即使现有容器定义的名称与类名称相同,并且即使该条目已经创建了相同类型的对象,也会发生这种情况。

仅辅助函数get()引用容器条目,而不引用类名(如Matthieu所介绍的那样)。

测试:

1)我定义了以下类别:

<?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)我定义了以下容器条目:

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)我执行了以下代码:

<?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)我收到以下结果:

Hello from MyTestClass. Input is: 12345
Hello from MyTestClass. Input is: NO INPUT
Hello from MyTestClass. Input is: NO INPUT

1 个答案:

答案 0 :(得分:1)

我邀请您在functions.php中检出这些函数的phpdoc。

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

这意味着createrouter类:该PHP类不存在。

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

这意味着autowirerouter(再次不存在)。

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

这意味着“当我要求RouterInterface::class时返回router条目。请注意,get()采用容器条目名称,而不是类名称。