Symfony 2 UniqueEntity repositoryMethod更新实体失败


Symfony 2 UniqueEntity repositoryMethod fails on Update Entity

我正在编写一些简单的脚本,但无法解决这个问题。

/**
 * 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

和repository Method

/**
     * 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约束,但在创建实体时,Id为空,因此存储库方法甚至不启动。此外,我试图删除实体,然后重新创建它。像

$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(),
        );
    }

Update操作

 /**
     * 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本身不工作,它在对象创建时为null,并且没有执行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
.
.
.
}