Я работаю над некоторым простым скриптом, но не могу оборачивать эту проблему. Так вот оно.
/** * Booking * @ORM\Table() * @ORM\Entity(repositoryClass="Tons\BookingBundle\Entity\BookingRepository") * @UniqueEntity(fields={"room", "since", "till"}, repositoryMethod="getInterferingRoomBookings") * @Assert\Callback(methods={"isSinceLessThanTill"}, groups={"search","default"}) */ class Booking
и метод репозитория
/** * Get room state for a certain time period * * @param array $criteria * @return array */ public function getInterferingRoomBookings(array $criteria) { /** @var $room Room */ $room = $criteria['room']; $builder = $this->getQueryForRoomsBooked($criteria); $builder->andWhere("ira.room = :room")->setParameter("room", $room); return $builder->getQuery()->getArrayResult(); }
Проблема в том, что это работает над созданием подобных методов, но при обновлении существующей сущности – это нарушает это ограничение.
Я попытался добавить Id constrain, но при создании сущностей id равен null, поэтому метод репозитория даже не запускается. Также я попытался удалить Entity, а затем воссоздал его. как
$em->remove($entity); $em->flush(); //----------- $em->persist($entity); $em->flush();
но это также не работает.
Создать действие
/** * Creates a new Booking entity. * * @Route("/create", name="booking_create") * @Method("POST") * @Template("TonsBookingBundle:Booking:new.html.twig") */ public function createAction(Request $request) { $entity = new Booking(); $form = $this->createForm(new BookingType(), $entity); $form->bind($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $room = $entity->getRoom(); if($room->getLocked() && $room->getLockedBy()->getId() === $this->getUser()->getId()) { $entity->setCreatedAt(new \DateTime()); $entity->setUpdatedAt(new \DateTime()); $entity->setManager($this->getUser()); $em->persist($entity); $room->setLocked(false); $room->setLockedBy(null); $room->setLockedAt(null); $em->persist($room); $em->flush(); return $this->redirect($this->generateUrl('booking_show', array('id' => $entity->getId()))); } else { $form->addError(new FormError("Номер в текущий момент не заблокирован или заблокирован другим менеджером")); return array( 'entity' => $entity, 'form' => $form->createView(), ); } } return array( 'entity' => $entity, 'form' => $form->createView(), ); }
Обновить действие
/** * Edits an existing Booking entity. * * @Route("/edit/{id}/save", name="booking_update") * @Method("PUT") * @Template("TonsBookingBundle:Booking:edit.html.twig") */ public function updateAction(Request $request, $id) { /** @var $em EntityManager */ $em = $this->getDoctrine()->getManager(); $entity = $em->getRepository('TonsBookingBundle:Booking')->find($id); if (!$entity) { throw $this->createNotFoundException('Unable to find Booking entity.'); } $editForm = $this->createForm(new BookingType(), $entity); $editForm->bind($request); if ($editForm->isValid()) { $em->persist($entity); $em->flush(); return $this->redirect($this->generateUrl('booking_edit', array('id' => $id))); } return array( 'entity' => $entity, 'form' => $editForm->createView(), ); }
Я получил это! Я изменил аннотацию к этому
/** * Booking * @ORM\Table() * @ORM\Entity(repositoryClass="Tons\BookingBundle\Entity\BookingRepository") * @UniqueEntity(fields={"id","room", "since", "till"}, repositoryMethod="getInterferingRoomBookings") * @UniqueEntity(fields={"room", "since", "till"}, repositoryMethod="getInterferingRoomBookings",groups={"create"}) * @Assert\Callback(methods={"isSinceLessThanTill"}, groups={"search","default"}) */ class Booking
Копировать BookingType в BookingTypeCreate и добавлено
public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Tons\BookingBundle\Entity\Booking', 'validation_groups' => array('create'), )); }
Формирование значений по умолчанию. Таким образом, теперь параметры различаются при передаче объекта методу проверки. Я думаю, что это все же метод обхода.
Краткий ответ: вы не получаете данные формы в сущности, поэтому вы работаете с новым сущностью, которая не знает, что ее комната установлена в форме.
Длинный ответ: получение данных формы и их размещение в сущности позволяет вам манипулировать данными перед обновлением. См. Измененный контроллер ниже. Ключевая строка
$entity = form->getData();
Что затем позволяет вам $room=$entity->getRoom();
/** * Creates a new Booking entity. * * @Route("/create", name="booking_create") * @Method("POST") * @Template("TonsBookingBundle:Booking:new.html.twig") */ public function createAction(Request $request) { $entity = new Booking(); $form = $this->createForm(new BookingType(), $entity); $form->bind($request); $entity = $form->getData(); // Lighthart's addition if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $room = $entity->getRoom(); if($room->getLocked() && $room->getLockedBy()->getId() === $this->getUser()->getId()) { $entity->setCreatedAt(new \DateTime()); $entity->setUpdatedAt(new \DateTime()); $entity->setManager($this->getUser()); $em->persist($entity); $room->setLocked(false); $room->setLockedBy(null); $room->setLockedAt(null); $em->persist($room); $em->flush(); return $this->redirect($this->generateUrl('booking_show', array('id' => $entity->getId()))); } else { $form->addError(new FormError("Номер в текущий момент не заблокирован или заблокирован другим менеджером")); return array( 'entity' => $entity, 'form' => $form->createView(), ); } } return array( 'entity' => $entity, 'form' => $form->createView(), ); }
Передайте дополнительный идентификатор (возможно, token
) в уникальное поле проверки (например, loginName
) ( fields={"token", "loginName"}
) в метод repositoryMethod. Сам id
не работает, он равен нулю при создании объекта, и метод repositoryMethod не выполняется. Я создаю token
в методе конструктора. Маркер необходим для идентификации объекта при создании или обновлении.
/** * @ORM\Table(name="anbieterregistrierung") * @ORM\Entity(repositoryClass="AnbieterRegistrierungRepository") * @UniqueEntity( * fields={"token", "loginName"}, * repositoryMethod="findUniqueEntity" * ) */
то в классе репозитория вы редактируете WHERE DQL:
public function findUniqueEntity(array $parameter) { $loginName = $parameter['loginName']; $token = $parameter['token']; . . . . . . WHERE anbieterregistrierung.loginName = :loginName AND anbieterregistrierung.token <> :token . . . }