Внедрение зависимостей Symfony 4 - конструктор против метода - PullRequest
0 голосов
/ 10 октября 2018

Итак, у меня есть контроллер Symfony, и я внедряю необходимые методы в мои методы с помощью параметров.

Один из параметров (MySqlGroupDAO $groupDAO) используется всеми методами этого класса контроллера.

В настоящее время я передаю «общий» параметр как мой последний параметр в каждом методе следующим образом:

/**
 * @Route("/{id}", methods={"POST"})
 * @IsGranted("EDIT_GROUP", subject="parentGroup")
 */
public function addGroup(Request $request, MySqlGroupDAO $groupDAO)  {
    $group = new Group();
    //code to init group from request

    $groupDAO->addGroup($group);

    return new Response("Adding $groupName");
}

Выполнение этого способа позволяет мне исключить мой __construct метод.Однако я не уверен, что это лучший способ сделать это.Поскольку это распространено во всех методах, было бы лучше повторно добавить мой конструктор и сделать что-то вроде этого:

private $groupDAO;

public function __construct(
    Config $config,
    ValidatorInterface $validator,
    TranslatorInterface $translator,
    RequestStack $requestStack
) {
    parent::__construct($config, $validator, $translator, $requestStack);
    $this->groupDAO = new MySqlGroupDAO($config);
}


/**
 * @Route("/{id}", methods={"POST"})
 * @IsGranted("EDIT_GROUP", subject="parentGroup")
 */
public function addGroup(Request $request)  {
    $group = new Group();
    //code to init group from request

    $this->groupDAO->addGroup($group);

    return new Response("Adding $groupName");
}

При этом я исключаю около полудюжины параметров во всех моих методах (в этом конкретном классе).Но я добавляю обратно в свой конструктор, что требует от меня добавить параметр класса и добавить несколько дополнительных параметров в мой конструктор, поскольку он расширяет другой класс.

Есть ли преимущество в том, чтобы сделать это одним способом по сравнению сДругое?

Спасибо.

1 Ответ

0 голосов
/ 10 октября 2018

Причины использования DI в методах маршрута контроллера:

  • Менее подвержен изменениям метода parent::__construct.Использование DI в конструкторе означает, что вы должны адаптировать свой код всякий раз, когда это меняется.Также обратите внимание, что некоторые комплекты Symfony могут предполагать, что контроллеры имеют определенную подпись, и это может усложнить для вас, если это не так.
  • Если хотя бы один из маршрутов не использует службу, с помощью этихдетализированные DI, мы избегаем создания сервиса, когда в этом нет необходимости (что может быть дорогостоящим, если у него есть собственные DI, которые еще не использовались где-то еще).Это может быть в основном компенсировано использованием lazy services .

Причины использования DI в конструкторе:

  • Inсервисы, отличные от контроллеров (и в методах, отличных от методов маршрутизации контроллеров, если таковые имеются), вы не можете использовать автопроводку.Если вы хотите внедрить свои зависимости, используя аргумент метода, вам придется вручную передавать эту зависимость при каждом вызове.Это, в свою очередь, означает, что какая бы служба ни вызывала этот метод, она сама должна иметь DI для требуемой службы.Таким образом, проблема смещена, но она не может быть смещена бесконечно, и в какой-то момент вы захотите использовать автоматическое подключение к родителю.

Альтернатива использованиюDI в конструкторе:

Вы также можете использовать инъекцию сеттера и настроить свой сервис таким образом .Функционально это очень похоже на использование DI в конструкторе, но оно обходит главный недостаток генерации другой подписи из родительского и требует больше усилий для поддержки, если родительский конструктор изменяется.

Вы также можете сделать это прощеиспользовать для услуг, которые вы часто вводите.Сделайте так, чтобы службы, которым нужен этот DI, реализовали интерфейс и сконфигурировали их с помощью _instanceof .Symfony делает это с помощью ContainerAwareInterface и даже имеет посредника в форме ContainerAwareTrait для объявления установщика и свойства.В вашем случае, если для нескольких сервисов требуется сервис MySqlGroupDAO, вы можете определить MySqlGroupDAOAwareTrait и MySqlGroupDAOAwareInterface, добавить запись MySqlGroupDAOAwareInterface в ваш services.yaml s _instanceof раздел и использовать черту и реализоватьинтерфейс в сервисах, которым нужен DI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...