Я разрабатываю приложение среднего масштаба, используя Symfony2 и Doctrine2. Я пытаюсь максимально структурировать свой код в соответствии с принципами SOLID. Теперь вот вопрос:
Для создания новых сущностей я использую Symfony Forms с прокси-объектами, то есть: я не привязываю форму непосредственно к моей сущности, а к другому классу, который будет передан к какой-либо службе, которая предпримет необходимые действия на основе полученных данных, то есть: прокси-класс служит DTO для этой службы, которую я назову Handler
. Теперь, учитывая, что Handler
не зависит от EntityManager
, где мне делать вызовы EntityManager::persist()
и EntityManager::flush()
? Обычно мне удобно помещать flush
в контроллер, но я не уверен в persist
, так как контроллер не должен ничего предполагать о том, что делает Handler
, и, возможно, Handler::handle
(метод, которому передаются данные формы) делает больше, чем просто сохраните новую сущность в базе данных. Одна идея состоит в том, чтобы создать несколько interfaces
для инкапсуляции flush
и persist
и передачи их, которые будут действовать как обертки вокруг EntityManager::flush()
и EntityManager::persist()
, но я не уверен в этом, поскольку EntityManager::flush()
может привести к нежелательным последствиям. Так что, может быть, я должен просто создать интерфейс вокруг persist
.
Итак, мой вопрос: где и как сделать вызов persist
и flush
, чтобы получить наиболее надежный код? Или я просто все усложняю в поисках лучших практик?
Где следует вызывать EntityManager::persist() и EntityManager::flush()
Ответы (3)
Если у вас есть служба, которая будет обрабатывать задачи ваших сущностей, для меня правильный путь — внедрить EntityManager в определение вашего сервиса и выполнять внутри него операции сохранения и сброса.
Другой способ продолжить, если вы хотите отделить эту логику, — создать EventSubscriber. и вызовите пользовательское событие из вашей "службы сущностей", когда вы будете готовы выполнять операции сохранения и сброса.
person
DonCallisto
schedule
17.08.2015
Как я уже сказал, я не хочу связывать свой сервис со всем EntityManager, но мне действительно нравится идея, основанная на событиях.
- person user2268997; 17.08.2015
@ user2268997: Я упомянул об этом только потому, что, если цель службы — применить некоторую логику к объектам и сохранить их, поскольку сохранение и сброс — это небольшие операции, определенные в другом месте, это может быть хорошим компромиссом: иногда просто следовать Золотое правило: мы склонны разрабатывать ненужные решения
- person DonCallisto; 17.08.2015
@ user2268997: ps вам нужен диспетчер вместо диспетчера сущностей, поэтому в какой-то момент вам придется что-то вводить;)
- person DonCallisto; 17.08.2015
Дело не в том, сколько вещей вы внедряете. В противном случае вы бы просто внедряли сервисный контейнер повсюду и делали с ним все, что хотите. Однако обработка вещей с использованием событий всегда требует действительно организованной кодовой базы и большого количества документации. В противном случае проект превращается в крошечные кусочки спагетти, которые просто разбросаны повсюду, что на самом деле хуже, чем множество спагетти в одном месте.
- person user2268997; 17.08.2015
@ user2268997: Я прекрасно понимаю, что вы здесь говорите. Кстати, мое наблюдение все еще в силе :)
- person DonCallisto; 17.08.2015
Мои 2 цента:
- о
flush
, поскольку он вызывает БД, делать это так же, как вы уже делаете, когда это необходимо в ваших контроллерах, звучит хорошо для меня. - о
presist
, его следует вызывать в вашемHandler
, когда ваша сущность находится в состоянии "готов к сбросу". ИнтерфейсPersister
только с методомpersist
в качестве зависимости от вашихHandler
, а внедренная в них реализацияDoctrinePersister
выглядит нормально.
person
Yassine Guedidi
schedule
17.08.2015
Другой вариант здесь - вы можете реализовать метод save()
в своем классе репозитория сущностей и сохранить его там. Вставьте свой репозиторий сущностей в качестве зависимости в свой класс Handler
.
person
Serhii Smirnov
schedule
22.01.2019