Symfony2表单 - 在提交时删除相关的实体表单

时间:2015-11-26 10:15:42

标签: php forms symfony doctrine-orm

我有一个来自CalendarMeeting的继承实体CalendarEvent,它添加了两个相关的实体。其中一个是Address实体。提交CalendarMeeting后,我想检查Address表单是否为空,如果是,请删除表单,以便不将Address保存到数据库中。我的代码如下:

CalendarMeeting

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping AS ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Entity\CalendarMeetingRepository")
 * @ORM\Table(name="calendar_meetings")
 */
class CalendarMeeting extends CalendarEvent
{
    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Address", cascade={"persist"})
     * @ORM\JoinColumn(name="address_id", referencedColumnName="id")
     */
    private $address;

    /**
     * @var ArrayCollection
     *
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\User")
     * @ORM\JoinTable(
     *     name="User2CalendarMeeting",
     *     joinColumns={@ORM\JoinColumn(name="calendar_meeting_id", referencedColumnName="id", nullable=false)},
     *     inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)}
     * )
     */
    private $users;



    /**
     * @return mixed
     */
    public function getAddress()
    {
        return $this->address;
    }

    /**
     * @param mixed $address
     * @return CalendarMeeting
     */
    public function setAddress($address)
    {
        $this->address = $address;

        return $this;
    }

    /**
     * @return ArrayCollection
     */
    public function getUsers()
    {
        return $this->users;
    }

    /**
     * @param User $user
     * @return void
     */
    public function addUser(User $user)
    {
        $this->users->add($user);
    }

    /**
     * @param User $user
     * @return void
     */
    public function removeUser(User $user)
    {
        $this->users->removeElement($user);
    }
}

Address实体:

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping AS ORM;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Entity\AddressRepository")
 * @ORM\Table(name="addresses")
 * @ORM\HasLifecycleCallbacks
 */
class Address
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    private $name;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    private $address_1;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    private $address_2;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    private $postal_code;

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    private $postal_address;

    /**
     * @ORM\Column(type="decimal", nullable=true, precision=10, scale=6)
     */
    private $latitude;

    /**
     * @ORM\Column(type="decimal", nullable=true, precision=11, scale=6)
     */
    private $longitude;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $created;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $updated;



    /**
     * @return mixed
     */
    public function getId() {
        return $this->id;
    }

    /**
     * @return mixed
     */
    public function getName() {
        return $this->name;
    }

    /**
     * @param mixed $name
     * @return Address
     */
    public function setName($name) {
        $this->name = $name;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getAddress1() {
        return $this->address_1;
    }

    /**
     * @param mixed $address_1
     * @return Address
     */
    public function setAddress1($address_1) {
        $this->address_1 = $address_1;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getAddress2() {
        return $this->address_2;
    }

    /**
     * @param mixed $address_2
     * @return Address
     */
    public function setAddress2($address_2) {
        $this->address_2 = $address_2;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getPostalCode() {
        return $this->postal_code;
    }

    /**
     * @param mixed $postal_code
     * @return Address
     */
    public function setPostalCode($postal_code) {
        $this->postal_code = $postal_code;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getPostalAddress() {
        return $this->postal_address;
    }

    /**
     * @param mixed $postal_address
     * @return Address
     */
    public function setPostalAddress($postal_address) {
        $this->postal_address = $postal_address;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getLatitude() {
        return $this->latitude;
    }

    /**
     * @param mixed $latitude
     * @return Address
     */
    public function setLatitude($latitude) {
        $this->latitude = $latitude;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getLongitude() {
        return $this->longitude;
    }

    /**
     * @param mixed $longitude
     * @return Address
     */
    public function setLongitude($longitude) {
        $this->longitude = $longitude;

        return $this;
    }


    /**
     * @return mixed
     */
    public function getCreated()
    {
        return $this->created;
    }

    /**
     * @param \DateTime $created
     * @return Address
     */
    public function setCreated(\DateTime $created)
    {
        $this->created = $created;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getUpdated()
    {
        return $this->updated;
    }

    /**
     * @param mixed $updated
     * @return ShiftChange
     */
    public function setUpdated(\DateTime $updated)
    {
        $this->updated = $updated;

        return $this;
    }

    /**
     * @ORM\PrePersist
     * @ORM\PreUpdate
     */
    public function updateTimestamps()
    {
        $this->setUpdated(new \DateTime('now'));

        if ($this->getCreated() === null) {
            $this->setCreated(new \DateTime('now'));
        }
    }
}

没有CalendarMeetingType只有继承的CalendarEventType,我在其中使用事件侦听器检查编辑的实体类型。它看起来像这样:

<?php

namespace AppBundle\Form;

use AppBundle\Entity\CalendarMeeting;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;

class CalendarEventType extends AbstractType
{
    protected $start = false;
    protected $end = false;

    public function __construct($date = null)
    {
        if ($date) {
            $this->start = new \DateTime($date . ' 09:00:00');
            $this->end = new \DateTime($date . ' 10:00:00');
        }

    }
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
          ->add('name', null, array(
            'attr' => array(
              'placeholder' => 'app.forms.calendar.name',
            ),
            'label' => 'app.forms.calendar.name',
            'translation_domain' => 'AppBundle'
          ))
          ->add('description', null, array(
            'label' => 'app.forms.calendar.description',
            'translation_domain' => 'AppBundle'
          ))
          ->add('event_type', 'choice', array(
            'label' => "app.forms.calendar.event_type.label",
            'choices' => array(
              'event' => 'app.forms.calendar.event_type.event',
              'meeting' => 'app.forms.calendar.event_type.meeting',
              'holiday' => 'app.forms.calendar.event_type.holiday',
            ),
            'required' => true,
            'expanded' => false,
            'multiple' => false,
            'mapped'   => false,
            'translation_domain' => 'AppBundle'
          ));

        if ($this->start && $this->end) {
          $builder
            ->add('start', 'datetime', array(
                'date_widget'        => 'single_text',
                'time_widget'        => 'text',
                'data'               => $this->start,
                'label'              => 'app.forms.calendar.start',
                'translation_domain' => 'AppBundle',
              ))
            ->add('end', 'datetime', array(
                'date_widget'        => 'single_text',
                'time_widget'        => 'text',
                'data'               => $this->end,
                'label'              => 'app.forms.calendar.end',
                'translation_domain' => 'AppBundle'
              ));
        } else {
          $builder
            ->add('start', 'datetime', array(
              'date_widget'        => 'single_text',
              'time_widget'        => 'text',
              'label'              => 'app.forms.calendar.start',
              'translation_domain' => 'AppBundle',
            ))
            ->add('end', 'datetime', array(
              'date_widget'        => 'single_text',
              'time_widget'        => 'text',
              'label'              => 'app.forms.calendar.end',
              'translation_domain' => 'AppBundle'
            ));
        }

      $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        array($this, 'onPreSetData')
      );

      $builder->addEventListener(
        FormEvents::PRE_SUBMIT,
        array($this, 'onPreSubmit')
      );
    }

  /**
   * @param \Symfony\Component\Form\FormEvent $event
   */
  public function onPreSetData(FormEvent $event)
  {
    $form = $event->getForm();
    $data = $event->getData();

    /* Check we're looking at the right data/form */
    if ($data instanceof CalendarMeeting) {
      $form->add('address', new AddressType());
    }
  }

  /**
   * @param \Symfony\Component\Form\FormEvent $event
   */
  public function onPreSubmit(FormEvent $event)
  {
    $data = $event->getData();
    $form = $event->getForm();

    if ($data instanceof CalendarMeeting) {
      if ($data->getAddress()->getAddress1() == "") {
        $form->remove('address');
      }
    }
  }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\CalendarEvent'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'appbundle_calendarevent';
    }
}

onPreSubmit功能显然不起作用,但唉,这是我希望这是正确的方法。我无法弄清楚如何解决这个问题(另一种方式)。

现在发生的事情是,当我在地址表单字段中提交没有任何数据的表单时,地址仅使用空值保存到数据库。如何在保存地址时停止该地址?

非常感谢你的时间。

此致 托米

1 个答案:

答案 0 :(得分:0)

我想出来了。我完全错了。解决方案是在onDelete="CASCADE" CalendarMeeting上添加address

(编辑:onDelete="CASCADE"已从联接列中删除,因为它不需要)

/**
 * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Address", cascade={"persist"})
 * @ORM\JoinColumn(name="address_id", referencedColumnName="id", nullable=true)
 */
private $address;

setAddress函数上,最初将address参数设置为null:

/**
 * @param Address $address
 * @return CalendarMeeting
 */
public function setAddress(Address $address = null)
{
    $this->address = $address;

    return $this;
}

然后在CalendarEventType我更改了address类型添加到以下内容,因此它接受null:

if ($data instanceof CalendarMeeting) {
  $form->add('address', new AddressType(), array(
    'required' => false,
  ));
}

最后在CalendarEventController中,我检查地址字段是否包含任何值。如果不是,请将地址设置为null:

// Check if calendar meeting
if($entity instanceof CalendarMeeting) {
    $address_form = $editForm->get('address')->getData();
    if($address_form === null ||
       ($address_form->getName() === null &&
       $address_form->getAddress1() === null &&
       $address_form->getPostalCode() === null &&
       $address_form->getPostalAddress() == null)
    ) {
        $entity->setAddress(null);
    }
}

$em->flush();

return ...redirect...

如果有人有更好的解决方案,请发一个答案,我会接受。此外,如果这是一个肮脏的解决方案,请评论。我有一种感觉.. :)