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 в любое время, просто изменив эту конфигурацию.