PHP-DI: создать против autowire против get. Или как правильно сопоставить интерфейс с реализацией, предоставленной определением
Для моего контейнера PHP-DI в веб-MVC я подготовил следующее определение для маршрутизатора:
return [
'router' => function (ContainerInterface $c) {
//...
return new Router(...);
}
];
Теперь я хочу сопоставить интерфейс (MyLib\Routing\RouterInterface
) к реализации, предусмотренной 'router'
запись. В документации PHP-DI я нашел три способа достижения этого. Что-то вроде этого:
RouterInterface::class => DI\create('router')
RouterInterface::class => DI\autowire('router')
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()
ни в коем случае не ссылаться на запись в контейнере. Они получают имя класса в качестве аргумента и проверяют, что объект этого класса НОВЫЙ (один раз). Это происходит, даже если имя существующего определения контейнера совпадает с именем класса, и даже если эта запись уже создает объект того же типа.
Исключительно вспомогательная функция get()
ссылается на записи контейнера, а не на имена классов (как любезно представил Матье).
Тестовое задание:
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 ответ
Я приглашаю вас проверить phpdoc этих функций в functions.php.
RouterInterface::class => DI\create('router')
Это означает create
router
класс: этот класс PHP не существует.
RouterInterface::class => DI\autowire('router')
Это означает autowire
router
класс (который опять не существует).
RouterInterface::class => DI\get('router')
Это значит "когда я прошу RouterInterface::class
вернуть router
запись. Заметить, что get()
принимает имя записи контейнера, а не имя класса.