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