Каковы причины для PHP Frameworks использовать Dependency Injection Container для создания объектов?
Я собираюсь сосредоточиться на Zend Framework, потому что я знаю его лучше, но это, безусловно, применимо к другим аналогичным механизмам, встречающимся в других PHP-фреймворках, которые используют контейнер Inverstion of Control.
В случае Zend Framework с небольшим рефакторингом / манипуляциями вполне возможно не использовать контейнер.
Рабочий пример
Глядя на документы, в настоящее время Zend Framework делает что-то подобное с $container
(взято отсюда):
function getServiceConfig()
{
return [
'factories' => [
Model\AlbumTable::class => function ($container)
{
$tableGateway = $container->get(Model\AlbumTableGateway::class);
return new Model\AlbumTable($tableGateway);
},
Model\AlbumTableGateway::class => function ($container)
{
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
}
]
];
}
//to call
$albumTable = $container->get(Model\AlbumTable::class)
Левая сторона =>
содержит "ключи", которые могут быть любой строкой, включая строку определения класса. Справа находится обратный вызов или полное доменное имя для имени класса. В приведенном выше примере это анонимная функция PHP, которая действует как фабрика для создания новой сущности, используя DiC $container
который передается этой функции через вызов Framework.
Почему бы не удалить контейнер и сделать что-то вроде этого:
//define
function AlbumTableFactory()
{
$tableGateway = AlbumTableGatewayFactory();
return new Model\AlbumTable($tableGateway);
}
function AlbumTableGatewayFactory()
{
$dbAdapter = AdapterInterface();
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Album());
return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
}
//to call
$albumTable = AlbumTableFactory();
Выше можно преобразовать в классы, если голые функции надоедают.
В вышеупомянутом я удалил $container
и заменил любое использование контейнера жестко закодированным new
вызовы функций и так как не было предоставленных параметров
Так как factories
массив является частью конфигурации контейнера Zend, чтобы по-настоящему его выделить, мне придется заменить любые другие экземпляры контейнера, вызывающего Model\AlbumTable::class
с фабричным вызовом, чтобы вернуть Model\AlbumTable
пример. Как только это будет сделано, у меня может появиться реализация без Zend-контейнера, где я буду вызывать фабрики напрямую, а не вызывать их через контейнер со всеми явно определенными зависимостями.
Суть вопроса в том, зачем использовать контейнер, что именно он обеспечивает, и почему бы просто не использовать "реальный код PHP" с тем преимуществом, что через контейнер не будут скрываться зависимости.