代码之家  ›  专栏  ›  技术社区  ›  dakis

php-di:创建vs.autowire vs.get。或者如何将接口正确映射到定义提供的实现

  •  2
  • dakis  · 技术社区  · 6 年前

    对于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')

    当我应用第3个选项时,所有选项都正常,例如,我可以使用以下命令检索接口条目:

    $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() 不要以任何方式引用容器中的条目。它们接收一个类名作为参数,并确保该类的对象是 新的 创建(一次)。即使现有容器定义的名称与类名相同,并且该条目已经创建了相同类型的对象,也会发生这种情况。

    仅辅助函数 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 回复  |  直到 6 年前
        1
  •  1
  •   Matthieu Napoli    6 年前

    functions.php

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

    create router

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

    autowire

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

    RouterInterface::class get()

    推荐文章