Всем привет, начал изучать паттерн dependency injection, вроде, все понятно и логично.
Насколько понял, для удобного управления зависимости используются специальные контейнеры.
Очень долгое время я не мог понять, как же используется этот контейнер на практике, какая область видимости у контейнера, и в какой момент в контейнер добавляют сервисы ?
Задав эти вопросы на форумах, мне посоветовали взять любой DI-контейнер, и попробовать с ним поработать, тогда и станет понятно.
Решил я взять очень простой DI-контейнер, от разработчиков symfony -
Pimple.
Написал класс
SystemBlock (системный блок) с 3-4 зависимостями:
- Блок питания
- Видеокарта
- Процессор
- Операционная система
Пример вызова класса
SystemBlock без контейнера:
<?php
use Less\SystemBlock;
$systemBlock = new SystemBlock\SystemBlock(
new SystemBlock\GigabytePower,
new SystemBlock\GeForceVideo,
new SystemBlock\IntelProcessor
);
$os = new SystemBlock\LinuxOS;
$os->setUser(new SystemBlock\OSUser("Вася", "Vasya", true));
$systemBlock->setOperatingSystem($os);
$systemBlock->start();
и пример с использованием контейнера:
<?php
use Less\SystemBlock;
$container = new \Pimple\Container;
$container["power"] = function ($c) {
return new SystemBlock\GigabytePower;
};
$container["video"] = function ($c) {
return new SystemBlock\GeForceVideo;
};
$container["processor"] = function ($c) {
return new SystemBlock\IntelProcessor;
};
$container["system_block"] = function ($c) {
return new SystemBlock\SystemBlock(
$c["power"],
$c["video"],
$c["processor"]
);
};
$systemBlock = $container["system_block"];
$os = new SystemBlock\LinuxOS;
$os->setUser(new SystemBlock\OSUser("Вася", "Vasya", true));
$systemBlock->setOperatingSystem($os);
$systemBlock->start();
Файлы с классами и интерфейсами выложил на
GitHub
Возникшие вопросы:
1. Правильно ли я понял, что сервисы в контейнер мы добавляем в файле единой точки входа в приложение ?
Что делать, если у меня у случая, когда нужно вызвать нужный сконфигурированный сервис загрузки товаров на сайт, например:
1.1. Загрузка происходит через файл
bin/import.php при запуске скрипта через крон.
1.2. При загрузка происходит через админку
admin/import.php сайта по кнопке.
В первом и втором случае мне необходим один и тот же сконфигурированный сервис. Мне необходимо в начале каждого файла
bin/import.php и
admin/import.php добавлять сервисы в контейнер и конфигурировать, или нужно вынести в отдельный общий файл ? Покажите пример пожалуйста, как это делается, и какие могут быть нюансы ?
. Из моих примеров управления зависимостями через контейнер и вручную, я не заметил никакой разницы. В чем преимущество контейнера ? Почему то, что я сделал вручную - неудобно ?
или контейнер нужен в тех случаях, когда один и тотже сервис используется несколько раз ? И в будущем удобно будет тестировать ? Заменил только в контейнере на тестовый сервис ?
И честно говоря, для меня самое сложное - это понять пункт
В каком месте приложения нужна инициализация контейнера ? Можно ли выносить в отдельный файл? Как подключать этот файл ? И т.д.
Я задал этот же вопрос на
другом форуме, где меня еще больше запутали, и теперь я не знаю, прав ли участник форума, который хочет мне помощь, или нет..
Уже долгое время не могу одолеть эту тему..