PHP-DI-это мощный и практичный фреймворк-независимый контейнер для инъекций зависимостей, написанный на PHP. Это руководство по лучшей практике использования PHP-DI и внедрения зависимостей.
Эта статья взята из PHP-DI, автор: Матье Наполи и соавтор. PHP-DI-это мощный и практичный фреймворк-независимый контейнер для инъекций зависимостей, написанный на PHP.
Исходный адрес: http://php -di.org/doc/best-pr…
Ссылки на PHP-DI в [Практическом каталоге с открытым исходным кодом нашего сайта]: http://www.worldlink.com.cn/o… Это руководство по лучшей практике использования PHP-DI и внедрения зависимостей.
Хотя он может охватывать не каждый случай и удовлетворять всех, он может послужить отправной точкой, которая поможет вам начать полагаться на инъекции.
Не имеет значения, согласны ли вы с чем-либо, объясненным в руководстве. Вы должны высказать свое собственное мнение по этим вопросам. Это не помешает вам использовать PHP-DI так, как вы хотите.
Ниже приведены некоторые основные правила:
Не получайте запись непосредственно из контейнера (всегда используя инъекцию зависимостей) В более общем плане, напишите код, разделяющий контейнеры, реализация которого для настройки в конфигурации контейнера для ограничений типа контроллера записи интерфейса С использованием инъекции зависимостей в контроллере обычно является наиболее болезненной.
Если мы возьмем в качестве примера Symfony2 (но это обычно применимо к любой платформе), вот ваш выбор:
Вставьте контроллер в контейнер и вызовите $container – > get (…) Это нехорошо. См.правило n степени 1.
Внедрение зависимостей в конструкторы (как контроллеры служб в Symfony) Это болезненно, когда у вас более пяти зависимостей, ваш конструктор состоит из 15 строк шаблонного кода
Введение зависимостей в атрибуты-это наше предлагаемое решение.
Например:
class UserController { /** * @Inject * @var FormFactoryInterface */ private $formFactory; public function createForm($type, $data, $options) { // $this->formFactory->... } }
Как вы можете видеть, это решение требует очень мало кода и легко для понимания и облегчения поддержки IDE (автоматическое завершение, рефакторинг,…).
Инъекция атрибутов обычно по какой-то причине хмурится:
Введение частных атрибутов нарушает инкапсуляцию. Это не явная зависимость: нет соглашения о том, что вашему классу необходимо настроить свойства для работы. Если вы используете аннотации PHP-DI для обозначения вводимых зависимостей, ваш класс зависит от контейнеров (см. Правило 2 выше). Но
Если вы будете следовать общим рекомендациям по написанию приложений, ваш контроллер не будет содержать бизнес-логики (только маршрутизация вызовов модели и привязка возвращаемых значений для просмотра).
Следовательно:
Вы не проводите модульное тестирование (что не означает, что вы не пишете функциональные тесты на интерфейсах). Вам не нужно повторно использовать его где-либо еще. Если вы измените структуру, вам, возможно, придется переписать ее (или ее части) (поскольку большинство зависимостей, таких как запросы, ответы, системы шаблонов и т.д., Изменятся) Это решение предлагает множество преимуществ без серьезных недостатков, поэтому мы рекомендуем использовать аннотации в контроллере.
Учитывая, что служба предназначена для повторного использования, тестирования и не зависит от вашей платформы, мы не рекомендуем вводить зависимости с аннотациями. Вместо этого мы рекомендуем использовать инъекцию конструктора и автоматическую сборку:
class OrderService implements OrderServiceInterface { private $paymentService; public function __construct(PaymentServiceInterface $paymentService) { $this->paymentService = $paymentService; } public function processOrder($order) { $this->paymentService->... } }
Используя автоматическую сборку (включена по умолчанию), вы сами сохраняете каждый параметр конструктора в конфигурации привязки. PHP-DI угадает, какой объект ему нужно ввести, проверив тип вашего параметра.
В некоторых случаях использования автоматической сборки недостаточно, потому что некоторые параметры будут скалярными (строка, int,…). На этом этапе вам нужно четко определить, что вы хотите ввести в скалярный параметр. Для этого вы можете:
Определите все инъекции методов/классов (т. е. Каждый параметр). Например:
//config.php возвращение [//config.php возвращение [
// ... OrderService::class => DI\object() ->constructor(DI\get(SomeOtherService::class), 'a value'),
]; ]; Или просто определите скалярные параметры, чтобы разрешить PHP-использовать автоматическую сборку. Например:
DI\object() ->constructorParameter('paramName', 'a value'), ];
Это решение обычно предпочтительнее, чтобы избежать переопределения всего.
Примечание: Как указано в правиле n 3, мы рекомендуем ограничивать типы интерфейсов. В этом случае вам нужно будет сопоставить интерфейс с реализацией, которую контейнер должен использовать в своей конфигурации:
При использовании библиотек, таких как регистраторы, ORM,… Иногда их необходимо настроить.
В этом случае мы рекомендуем определить эти зависимости в файле конфигурации. Мы также рекомендуем использовать анонимные функции, когда конфигурация несколько сложна.
Анонимные функции позволяют вам писать реальный PHP-код, что здорово, потому что вы можете использовать библиотечные документы, получать поддержку IDE, как разработчик PHP, вы понимаете:.
Вот пример, Монолог, PHP-рекордер:
DI\factory(function () { $logger = new Logger('mylog'); $fileHandler = new StreamHandler('path/to/your.log', Logger::DEBUG); $fileHandler->setFormatter(new LineFormatter()); $logger->pushHandler($fileHandler); return $logger; }), ];
Конечно, как вы можете видеть, мы используем интерфейс PSR-3 для инъекций. Таким образом, мы можем заменить Монолог любым рекордером PSR-3 в любое время, просто изменив эту конфигурацию.