[英]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. 我让用户以一种形式而不是两种不同的形式来保存
Brands
和Cars
数据,但是对于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.