Где следует вызывать EntityManager::persist() и EntityManager::flush()

Я разрабатываю приложение среднего масштаба, используя 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, чтобы получить наиболее надежный код? Или я просто все усложняю в поисках лучших практик?


person user2268997    schedule 17.08.2015    source источник


Ответы (3)


Если у вас есть служба, которая будет обрабатывать задачи ваших сущностей, для меня правильный путь — внедрить EntityManager в определение вашего сервиса и выполнять внутри него операции сохранения и сброса.

Другой способ продолжить, если вы хотите отделить эту логику, — создать EventSubscriber. и вызовите пользовательское событие из вашей "службы сущностей", когда вы будете готовы выполнять операции сохранения и сброса.

person DonCallisto    schedule 17.08.2015
comment
Как я уже сказал, я не хочу связывать свой сервис со всем EntityManager, но мне действительно нравится идея, основанная на событиях. - person user2268997; 17.08.2015
comment
@ user2268997: Я упомянул об этом только потому, что, если цель службы — применить некоторую логику к объектам и сохранить их, поскольку сохранение и сброс — это небольшие операции, определенные в другом месте, это может быть хорошим компромиссом: иногда просто следовать Золотое правило: мы склонны разрабатывать ненужные решения - person DonCallisto; 17.08.2015
comment
@ user2268997: ps вам нужен диспетчер вместо диспетчера сущностей, поэтому в какой-то момент вам придется что-то вводить;) - person DonCallisto; 17.08.2015
comment
Дело не в том, сколько вещей вы внедряете. В противном случае вы бы просто внедряли сервисный контейнер повсюду и делали с ним все, что хотите. Однако обработка вещей с использованием событий всегда требует действительно организованной кодовой базы и большого количества документации. В противном случае проект превращается в крошечные кусочки спагетти, которые просто разбросаны повсюду, что на самом деле хуже, чем множество спагетти в одном месте. - person user2268997; 17.08.2015
comment
@ 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