简体   繁体   English

由于1-n的唯一性约束,无法持久

[英]Unable to persist because of uniqueness constraints for 1-n

I let users persist Brands and Cars data in a single form instead of having two different forms however I'm getting an error message " The Brand already exist in database. " for those brands which already exist in Brands table. 我让用户以一种形式而不是两种不同的形式来保存BrandsCars数据,但是对于Brands表中已经存在的那些品牌,我收到一条错误消息“ The Brand已经存在于数据库中。 How it should work is: if the brand name already exists then don't try to persist it again because name field is marked as unique in database. 它应该如何工作:如果品牌名称已经存在,则不要尝试再次保留它,因为name字段在数据库中被标记为唯一。 How can I solve this issue? 我该如何解决这个问题?

Note: The reason why I have two extra form types is because I also have two different interfaces to collect brands and cars data individually. 注意:之所以要使用两种额外的表单类型,是因为我还有两个不同的界面来分别收集品牌和汽车数据。

CONTROLLER 控制器

public function createAction(Request $request)
{
    if ($request->getMethod() != 'POST')
    {
        return new Response('Only POST method is allowed');
    }

    $form = return $this->createForm(new BothType(), null,
            array('action' => $this->generateUrl('bothCreate')));

    $form->handleRequest($request);

    if ($form->isValid())
    {
        $brandsData = $form->get('brands')->getData();
        $carsData = $form->get('cars')->getData();

        $brands = new Brands();
        $brands->setName($brandsData->getName());

        $cars = new Cars();
        $cars->setModel($carsData->getModel());
        $cars->setBrands($brands);

        $em = $this->getDoctrine()->getManager();
        $em->persist($brands);
        $em->persist($cars);
        $em->flush();

        return $this->redirect($this->generateUrl('both'));
    }

    return $this->render('CarBrandBundle:Default:both.html.twig',
            array('page' => 'Both', 'form' => $form->createView()));
}

BOTH TYPE 两种类型

class BothType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->setMethod('POST')
            ->setAction($options['action'])
            ->add('brands', new BrandsType())
            ->add('cars', new CarsType())
            ->add('button', 'submit', array('label' => 'Add'))
            ;
    }
} 

BRANDS ENTITY 品牌实体

/**
 * @ORM\Entity
 * @ORM\Table(name="brands", uniqueConstraints={@ORM\UniqueConstraint(columns={"name"})})
 * @UniqueEntity(fields="name", message="The Brand already exist in database.")
 * @package Car\BrandBundle\Entity
 */
class Brands
{
    protected $id;
    protected $name;

    /**
     * @ORM\OneToMany(targetEntity="Cars", mappedBy="brands")
     */
    protected $cars;

    public function __construct() { $this->cars = new ArrayCollection(); }

    public function getId() { return $this->id; }
    public function setName($name) { $this->name = $name; return $this; }
    public function getName() { return $this->name; }

    public function addCar(\Car\BrandBundle\Entity\Cars $cars)
    {
        $this->cars[] = $cars;
        return $this;
    }

    public function removeCar(\Car\BrandBundle\Entity\Cars $cars)
    {
        $this->cars->removeElement($cars);
    }

    public function getCars()
    {
        return $this->cars;
    }
}

BRANDS TYPE 品牌类型

class BrandsType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->setAction($options['action'])
            ->setMethod('POST')
            ->add('name', 'text', array('label' => 'Name'))
            ->add('button', 'submit', array('label' => 'Add'))
        ;
    }
}

CARS ENTITY 汽车实体

class Cars
{
    protected $id;
    protected $model;

    /**
     * @ORM\ManyToOne(targetEntity="Brands", inversedBy="cars")
     * @ORM\JoinColumn(name="brands_id", referencedColumnName="id", nullable=false)
     */
    protected $brands;

    public function getId() { return $this->id; }
    public function setModel($model) { $this->model = $model; return $this; }
    public function getModel() { return $this->model; }

    public function setBrands(\Car\BrandBundle\Entity\Brands $brands = null)
    {
        $this->brands = $brands;
        return $this;
    }

    public function getBrands()
    {
        return $this->brands;
    }
}

CARS TYPE 车种

class CarsType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->setAction($options['action'])
            ->setMethod('POST')
            ->add('model', 'text', array('label' => 'Model'))
            ->add('price', 'text', array('label' => 'Price'))
            ->add('button', 'submit', array('label' => 'Add'))
        ;
    }
} 

Solved by using form model which is not mapped to database so that I could ignore uniqueness check which was causing the whole problem. 通过使用未映射到数据库的表单模型解决,因此我可以忽略导致整个问题的唯一性检查。

1. Create a new Model called BothModel which is not mapped to database: 1.创建一个名为BothModel的新模型,该模型未映射到数据库:

class BothModel
{
    /**
     * @Assert\NotBlank(message="The Name field should not be blank")
     */
    protected $name;

    /**
     * @Assert\NotNull(message="The Origin field should not be blank")
     */
    protected $origin;

    /**
     * @Assert\NotNull(message="The Model field should not be blank")
     */
    protected $model;

    /**
     * @Assert\NotNull(message="The Price field should not be blank")
     */
    protected $price;


    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setOrigin($origin)
    {
        $this->origin = $origin;
        return $this;
    }

    public function getOrigin()
    {
        return $this->origin;
    }

    public function setModel($model)
    {
        $this->model = $model;
        return $this;
    }

    public function getModel()
    {
        return $this->model;
    }

    public function setPrice($price)
    {
        $this->price = $price;
        return $this;
    }

    public function getPrice()
    {
        return $this->price;
    }
} 

2. Update BothType and add form fields individually rather than initiating Brands and Cars form types. 2.更新BothType并单独添加表单字段,而不是启动Brands和Cars表单类型。

class BothType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->setMethod('POST')
            ->setAction($options['action'])
            ->add('name', 'text', array('label' => 'Name'))
            ->add('origin', 'text', array('label' => 'Origin'))
            ->add('model', 'text', array('label' => 'Model'))
            ->add('price', 'text', array('label' => 'Price'))
            ->add('button', 'submit', array('label' => 'Add'))
            ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array('data_class' => 'Car\BrandBundle\Form\Model\BothModel'));
    }

    public function getName()
    {
        return 'both';
    }
} 

3. Update the controller accordingly: 3.相应地更新控制器:

public function createAction(Request $request)
{
    if ($request->getMethod() != 'POST')
    {
        return new Response('Only POST method is allowed');
    }

    $form = $this->createForm(new BothType(), new BothModel(),
            array('action' => $this->generateUrl('bothCreate')));

    $form->handleRequest($request);

    if ($form->isValid())
    {
        $submission = $form->getData();

        $repo = $this->getDoctrine()->getRepository('CarBrandBundle:Brands');
        $brands = $repo->findOneBy(array('name' => $submission->getName()));

        if (! $brands)
        {
            $brands = new Brands();
            $brands->setName($submission->getName());
            $brands->setOrigin($submission->getOrigin());
        }

        $cars = new Cars();
        $cars->setModel($submission->getModel());
        $cars->setPrice($submission->getPrice());
        $cars->setBrands($brands);

        $em = $this->getDoctrine()->getManager();
        $em->persist($brands);
        $em->persist($cars);
        $em->flush();

        //return new Response('Brands ID: ' . $brands->getId() . ' - Cars ID: ' . $cars->getId());

        return $this->redirect($this->generateUrl('both'));
    }

    return $this->render('CarBrandBundle:Default:both.html.twig',
            array('page' => 'Both', 'form' => $form->createView()));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM