У меня есть проект, написанный на Symfony 4 (при необходимости можно обновить до последней версии). В нем у меня ситуация похожа на эту:
Есть контроллер, который отправляет запросы во внешнюю систему. Он просматривает записи в БД и отправляет запрос на каждую строку. Для этого существует класс MagicApiConnector
, который подключается к внешней системе, и для каждого запроса существует класс XxxRequest
(например, FooRequest
, BarRequest
и т. Д.).
Итак, что-то вроде этого общего:
foreach ( $allRows as $row ) {
$request = new FooRequest($row['a'], $row['b']);
$connector->send($request);
}
Теперь, чтобы выполнить всю магию заполнения параметров, запросы должны получить доступ к сервису, который определен в DI Symfony. Сам контроллер не знает и не заботится об этой услуге, но запросам она нужна.
Как мои классы запросов могут получить доступ к этой услуге? Я не хочу устанавливать это как зависимость от контроллера - я мог бы, но это вроде как неловко, так как контроллер действительно не заботится об этом и только пропустит его. Это деталь реализации запроса, и мне кажется, что это не должно обременять пользователей запроса этим стандартным требованием.
Опять же, иногда вам нужно приносить жертву во имя большего блага, так что, возможно, это один из таких случаев? Такое ощущение, что я "иду против зерна" и не понял какой-то идеологической концепции.
Добавлено: ОК, все подробности, без упрощений.
Все это происходит в контексте двух доморощенных систем. Давайте назовем их OldApp и NewApp. Оба являются API, и NewApp вызывает OldApp. API - это простой стиль REST / JSON. OldApp не построен на Symfony (в основном даже не использует фреймворк), а NewApp. Мой вопрос о NewApp.
Аутентификация для API OldApp поставляется в трех различных вариантах и может получить больше в будущем, если потребуется (это еще не конец!). Различные вызовы API используют разные методы аутентификации; иногда даже один и тот же вызов API можно использовать с разными методами (в зависимости от того, кто его вызывает). Все эти методы аутентификации также являются доморощенными. Один использует поля POST, другой использует пользовательские заголовки HTTP, не помню про третий.
Теперь NewApp вызывается приложением Android, которое распространяется среди многих пользователей. Android-приложение на самом деле использует как NewApp, так и OldApp. Когда он вызывает NewApp, он передает дополнительные заголовки HTTP с данными аутентификации для OldApp (метод 1). Таким образом, NewApp может выдать себя за пользователя приложения Android для OldApp. Кроме того, NewApp также необходимо использовать специальную команду OldApp, которую сами пользователи не могут вызвать (вопрос привилегий). Поэтому он использует другой механизм аутентификации (метод 2) для этой команды. Параметры этой команды хранятся в локальной конфигурации (переменные среды).
До меня коллега создал схему APIConnector
и APICommand
, где вы получаете соединитель в качестве зависимости и создаете экземпляры команд по мере необходимости. Коннектор фактически выполняет HTTP-запрос; команды сообщают ему, какие поля POST и какие заголовки отправлять. Я хочу сохранить эту схему.
Но как теперь разные механизмы аутентификации вписываются в это? Каждая команда должна быть в состоянии передать то, что ей нужно, соединителю; и механизмы должны быть многоразовыми для нескольких команд. Но одному нужен доступ к входящему запросу, другому нужен доступ к параметрам конфигурации. И ни то, ни другое не создается через DI. Как это сделать элегантно?