Как показывает практика, если писать на Symfony опираясь на документацию, фреймворк "подталкивает" пользователя к использованию слоев приложения со своей зоной ответственности. К примеру, общение с бд идет через репозиторий, бизнес-логику чаще всего описывают в модели, дробля на сервисы. Хоть и следовать документации - хорошее дело, пользователи, руководствуясь собственным опытом или той/иной методологией, вольны создавать собственные слои.
У меня возникла необходимость создать следующее:
- Слой, отвечающий за атомарные операции с бд (прим. - save(), delete(), может какой-то цикл с небольшой логикой)
- Разделение команды на инициализацию, и её выполнение. Были идеи для выделения выполнения в отдельный сервис, но что в таком случае делать с output'ом? (Примерно так же как и handler в Messenger компоненте)
То что описано в пункте про "атомарные операции" больше всего похоже на методы в entity repository в Doctrine.
Если эти операции специфичны для каких-то конкретных entity - можно реализовывать прямо в методах соответствующих репозиториев
Если они общие для всех entities - то проще всего вынести их в промежуточный абстрактный repository и наследовать остальные custom repositories от него
Если они общие для части entities - можно, к примеру, определить дополнительные интерфейсы, показывающие какие операции применимы к каким entities (у меня, например, зачастую используется ActivitableInterface для entities для которых есть флаг isActive) и дальше либо реализовать промежуточный абстрактный класс репозитория и наследовать custom repositories от него либо вынести эти операции в traits и подключать по мере необходимости.
Про "команды" не очень понятно, это про класс Command из symfony/command? Если да - то там есть раздельная инициализация через initialize(), туда передаётся OutputInterface и если сильно нужно - можно там вызвать некий отдельный сервис. Если не хочется прокидывать сервис вручную в каждую команду - можно автоматизировать это через setter + compiler pass либо через аннотицию@required
HEKET313 Можно в любой версии Symfony (начиная со 2-й), просто в данном случае это может быть неудобно, ведь речь идёт не о полностью собственном классе, а о наследнике EntityRepository, который, как мы помним, имеет собственный конструктор. Использование setter'а в данном случае более предпочтительно т.к. во-первых не вмешивается в базовый конструктор, а во-вторых его можно вынести в trait если потребуется.
- Слой, отвечающий за атомарные операции с бд (прим. - save(), delete(), может какой-то цикл с небольшой логикой)
save() - это flush() в энтити менеджере
delete() есть в реаозитории
какой-то цикл с небольшой логикой лучше реализовать в сервисе
Если ко всему этому нужно докрутить какую-то логику - то опять же с этим отлично справится сервис