Рубрики
Uncategorized

Лучшие практики PHP-DI и внедрения зависимостей

Автор оригинала: David Wong.

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