Symfony You should either make the service public, or stop using the container directly and use dependency injection instead.

Фанат

oncle terrible
Команда форума
Ситуация
У разных клиентов разные требования к скачиванию их файлов, поэтому есть набор небольших классов - хелперов, которые релизуют необходимый функционал.
В конфиге задается имя хелпера и потом тупо из контейнера по нему достаётся нужный.

Но вот Симфони ругается, и я в общем понимаю, почему.
И по этой причине делать эти сервисы публичными не хочу.

Но не имею ни малейшего понятия, как сделать правильно.
Как вообще решаются такие ситуации, когда через DI передать имя сервиса, но оно зависит от выбора пользователя?
 
Последнее редактирование:

флоппик

promotor fidei
Команда форума
Партнер клуба
Как вообще решаются такие ситуации, когда через DI передать имя сервися, но оно зависит от выбора пользователя?
Если в резолвинге зависимости участвует дополнительный критерий, нужно резолвить реализацию с учетом этого критерия. Либо в зависимости от этого критерия наполнять контейнер (например: миддлвара проверяет этот клиентский параметр, и биндит какой нибудь DirectFileDownload к FileDownloadingInterface, который ты указываешь, как зависимость) либо резолвить целиком фабрику с этими реализациями (возможно, как кложуру с параметром-зависимостью, т.е. с точки зрения места вызова все равно депендится интерфейс, просто динамически резолвится).
 

Adelf

Administrator
Команда форума
Не проще просто получить фабрику, которая и создаст необходимое по параметрам. Причем не симфониевскую, как описано по ссылкам, а простую - с методом, принимающим параметры.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
@Фанат ты свой набор хелперов не связываешь с приложением, это у тебя как стороняя библиотека? проще именно так, и тогда проще сделать сразу в ней абстрактную фабрику
Такое ощущение, что от симфони тут нужен только DI абстрактной фабрики в сервисный слой.
 

Фанат

oncle terrible
Команда форума
@grigori ну вообще в данный момент это просто часть приложения, хотя можно конечно вынести отдельно, но я не очень понимаю, зачем.
Эх, все эти термины конечно очень красивые, но я пока пытаюсь въехать в то что флопик написал, а ты ещё подкидываешь :)
Еще там нашлась такая штука сервис локатор, которая чисто по названию именно то что мне нужно.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
я пока пытаюсь въехать в то что флопик написал, а ты ещё подкидываешь :)
Я предлагаю сделать тебе примерно так:

Везде в конкретных call sites депендится Partner, но реализацию ты получаешь, или демо, или реального, загруженного партнера.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Не проще просто получить фабрику, которая и создаст необходимое по параметрам. Причем не симфониевскую, как описано по ссылкам, а простую - с методом, принимающим параметры.
Если честно, мне такое решение кажется приемлемым только как промежуточный этап рефакторинга. У тебя нет _зависимости_ от фабрики в этом месте кода. Тебе нужны просто разные _реализации_ одной и той же зависимости: скачивалки файла. Весь смысл DI в ресолвинге _нужных_ зависимостей, автовайринги всякие - это побочка, приятный синтаксический сахар. Тебе не нужна фабрика, тебе нужна реализация.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Еще там нашлась такая штука сервис локатор, которая чисто по названию именно то что мне нужно.
Не надо, правда. Я тебя отговариваю, потому что помню, сколько времени сам потратил, чтобы самому себе голову в нужную сторону потом отвернуть. Депенденси инджекшон именно потому инджекшон, потому что логика прямо противоположная: не проси никакие сервисы, реализации. Пиши код, как будто они уже есть, и сконфигурены правильно. Бизнес-логику не должна тревожить нижележащая инфраструктура, выбор и настройка нужной тебе реализации - и дело контейнера и его сервис провайдеров. Бизнес-логика полагается на контракты-интерфейсы, не на реализацию.
 

Adelf

Administrator
Команда форума
Если честно, мне такое решение кажется приемлемым только как промежуточный этап рефакторинга. У тебя нет _зависимости_ от фабрики в этом месте кода. Тебе нужны просто разные _реализации_ одной и той же зависимости: скачивалки файла. Весь смысл DI в ресолвинге _нужных_ зависимостей, автовайринги всякие - это побочка, приятный синтаксический сахар. Тебе не нужна фабрика, тебе нужна реализация.
мне всегда больше нравится явное против неявного. новый чел на проекте увидев фабрику сразу все поймет. а когда неизвестно откуда правильная имплементация прилетает... причем зависимая от партнера,который откуда берется(я не очень понимаю, реально :) )? а если мы из консоли работаем?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
А почему ты считаешь фабрику чем-то более явным, чем контракт?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
зависимая от партнера,который откуда берется(я не очень понимаю, реально :) )? а если мы из консоли работаем?
Бизнес-логике должно быть похер. Прилетает партнер. Какой, почему, с точки зрения бизнес-логики неважно. Просто операционная сущность такая - партнер. Какая разница, в консоли ты его из csv спарсил, это двойник-пустышка из тестов, или он из базы загрузился?
 

Adelf

Administrator
Команда форума
Бизнес-логике должно быть похер. Прилетает партнер. Какой, почему, с точки зрения бизнес-логики неважно. Просто операционная сущность такая - партнер. Какая разница, в консоли ты его из csv спарсил, это двойник-пустышка из тестов, или он из базы загрузился?
я имею ввиду, как этот партнер, от которого зависит какой загрузчик заинжектится, попадает в ту, симфониевскую фабрику?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
да, @Фанат ты лучший по холиворам, давно темы не было

я имею ввиду, как этот партнер, от которого зависит какой загрузчик заинжектится, попадает в ту, симфониевскую фабрику?
Если сервису сначала надо вызывать сonfigurator - это та же абстрактная фабрика, только вызывается из ci-контейнера, а не напрямую.

Какой ламер писал этот спойлер для форума, который работает, как 3.11 на 286 процессоре, у проца даже кулер включается - так сильно нагружает проц простая анимация.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Везде в конкретных call sites депендится Partner, но реализацию ты получаешь, или демо, или реального, загруженного партнера.
В каком классе у тебя этот registerPartnerIntegrationService()?

Кто вызывает registerPartnerIntegrationService() - DI-контейнер при создании Partner?

Фанату нужен не партнер, а хелпер. Партнер только определяет, какой будет хелпер. PartnerServiсeProvider, видимо, получает в конструктор DI-контейнер, и в него добавляет что-то по команде register(). Что он регистрирует?
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Имхо, в идеологии Симфони, это делается на уровне конфигов.
И Сервис локатор как раз оно и должно быть. Но я еще не до конца разобрался.
В идеологии симфони ты пишешь эти хелперы как компоненты, и реюзаешь в разных проектах. Вопрос - зачем?

1: абстрактная фабрика
+ ясно, просто: регаем фабрику в dependency, у фабрики в зависимостях партнер, из фабрики получаем хелпер
- зависимость от фабрики, пахнет костылем и недостойно высоких этических норм низкоуровневой архитектуры мечты
2: DI
+ получаем подготовленный правильный хелпер как сервис "магически" прямо в параметр
- обвешиваемся 3 дополнительными классами - сервис инициализации, сервис интеграции, сервис инициализации сервиса интеграции
3. колбек конфигуратора
как второй, только все три класса объединяются в один, с привязкой к соглашениям конкретной версии симфони
 

Adelf

Administrator
Команда форума
Честно говоря, все эти обвешивания паттернами и поклонение "идеологии Симфони" напоминает мне культ карго.
Задача - получать нужный загрузчик для переданного партнера.
делаем класс
Код:
class LoaderFactory {
    public function getLoader(Partner $partner): Loader
    { .... }
}
Можно даже интерфейс присобачить, если очень хочется. И просить этот класс(или интерфейс).
Никто не запрещает сконфигурить эти соответствия партнеров и загрузчиков в конфигурации и использовать эту конфигурацию в LoaderFactory. Или сконфигурить все в базе и использовать это.

Явная зависимость от фабрики, как по мне, лучше неявной.

у фабрики в зависимостях партнер
В случае SAAS, когда партнер фетчится.. допустим по URL сайта или подобным образом, можно и так... но придется везде жесткие правила вводить. Например, чтобы и через консольную команду тоже этот партнер как-то доставался. И допустим если у вас телеграмм бот висит в этом же монолите. и т.д.
Явно передавать партнера в разы проще.

Ну и да. Загрузка файлов - это не бизнес-логика. Не надо бояться испачкаться :) Правильно изолированная бизнес-логика вообще ни про какие зависимости не знает.
 
Сверху