![](/img/trans.png)
[英]Getting “Integrity constraint violation: 1048 Column 'payment_id' cannot be null” using Doctrine & Symfony
[英]Symfony 3 : Embed Collection of Forms persistence issue : Integrity constraint violation: 1048 Column 'arrivage_id' cannot be null
我正在使用Symfony 3.4 lts ,但是嵌入式集合表單持久性出現問題。
此問題要求Symfony Expert ..該描述看起來很長,但是它是Symofny CLI默認命令自動生成的代碼的80%。
我是還原專家,因此您會發現我的描述簡單且具有教學意義,
這個簡單的UML圖類描述了我的3個實體
代碼是法語,因此Arrival是Arrivage,product是Produit,中間實體ArrivalElement是ElementArrivage。
/**
* Arrivage
*
* @ORM\Table(name="arrivage")
* @ORM\Entity(repositoryClass="AppBundle\Repository\ArrivageRepository")
*/
class Arrivage
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var \DateTime
*
* @ORM\Column(name="dateCreation", type="datetime")
*/
private $dateCreation;
/**
* @var Arrivage
* @ORM\OneToMany(targetEntity="ElementArrivage", mappedBy="arrivage", cascade={"persist", "remove"}, orphanRemoval=TRUE)
*/
private $elementArrivages;
public function __construct() {
$this->dateCreation = new \DateTime();
$this->elementArrivages = new ArrayCollection();
}
// bin/console doctrine:generate:entities AppBundle:Arrivage => OK
/**
* ElementArrivage
*
* @ORM\Table(name="element_arrivage")
* @ORM\Entity(repositoryClass="AppBundle\Repository\ElementArrivageRepository")
*/
class ElementArrivage
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var Arrivage
*
* @ORM\ManyToOne(targetEntity="Arrivage", inversedBy="elementArrivages")
* @ORM\JoinColumn(name="arrivage_id", referencedColumnName="id", nullable=FALSE)
*/
private $arrivage;
/**
* @var Produit
*
* @ORM\ManyToOne(targetEntity="Produit", inversedBy="elementArrivages")
* @ORM\JoinColumn(name="produit_id", referencedColumnName="id", nullable=FALSE)
*/
private $produit;
/**
* @var int
*
* @ORM\Column(name="quantite", type="integer")
*/
private $quantite;
/**
* @var string
*
* @ORM\Column(name="prix_achat", type="decimal", precision=10, scale=3)
*/
private $prixAchat;
// bin/console doctrine:generate:entities => OK
/**
* Produit
*
* @ORM\Table(name="produit")
* @ORM\Entity(repositoryClass="AppBundle\Repository\ProduitRepository")
*/
class Produit
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, unique=true)
*/
private $name;
/**
* @var Arrivage
* @ORM\OneToMany(targetEntity="ElementArrivage", mappedBy="produit", cascade={"persist", "remove"}, orphanRemoval=TRUE)
*/
private $elementArrivages;
// bin/console doctrine:generate:entities => OK
class ArrivageType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('elementArrivages', CollectionType::class, array(
'entry_type' => ElementArrivageType::class,
'allow_add' => true,
'allow_delete' => true,
'label'=> false,
'entry_options' => array(
'label' => false
)
))
;
}/**
class ElementArrivageType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('quantite')
->add('prixAchat')
->add('produit', EntityType::class, array(
// looks for choices from this entity
'class' => 'AppBundle:Produit',
// uses the User.username property as the visible option string
'choice_label' => 'name',
// used to render a select box, check boxes or radios
// 'multiple' => true,
// 'expanded' => true,
));
;
}/*
所以我的主要實體是到達,我必須創建一個到達,它必須在Cascade上保持其余部分,以便我必須為到達實體創建一個控制器
經理論產生結垢后仍然干凈
我使用文檔技術(原型)來創建新的elementArrivage
文件: https : //symfony.com/doc/3.4/form/form_collections.html#allowing-new-tags-with-the-prototype
演示javascript: http : //jsfiddle.net/847Kf/4/
使用這種配置,在嘗試創建新的到達時,我遇到了第一個持久性問題:
An exception occurred while executing 'INSERT INTO element_arrivage (quantite, prix_achat, prixVente, arrivage_id, produit_id) VALUES (?, ?, ?, ?, ?)' with params [1, 1, 1, null, 11]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'arrivage_id' cannot be null
我通過在方法的“實體到達”中添加一行來解決此問題:
public function addElementArrivage(\AppBundle\Entity\ElementArrivage $elementArrivage)
{
$elementArrivage->setArrivage($this); // Added Liiiiiiiiiiiiiiiiiiine
$this->elementArrivages[] = $elementArrivage;
return $this;
}
第一個問題:這是一個適當的解決方案嗎?
解決了第一個問題之后,我得到了第二個問題:
An exception occurred while executing 'INSERT INTO element_arrivage (quantite, prix_achat, prixVente, arrivage_id, produit_id) VALUES (?, ?, ?, ?, ?)' with params [1, 1, 1, null, 11]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'arrivage_id' cannot be null
第二個問題:我對解決方案一無所知,但是當我嘗試使用此行修改Controller時,問題消失了,但這不是解決方案,因為在這種情況下ElementArrivage將固定為兩個:
/**
* Creates a new arrivage entity.
*
* @Route("/new", name="arrivage_new")
* @Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$arrivage = new Arrivage();
$elementArrivage = new ElementArrivage(); //Added Liiiiines begin
$elementArrivage2 = new ElementArrivage();
$arrivage->addElementArrivage($elementArrivage);
$arrivage->addElementArrivage($elementArrivage2); // Added Liiiines end
$form = $this->createForm('AppBundle\Form\ArrivageType', $arrivage);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($arrivage);
$em->flush();
return $this->redirectToRoute('arrivage_show', array('id' => $arrivage->getId()));
}
return $this->render('arrivage/new.html.twig', array(
'arrivage' => $arrivage,
'form' => $form->createView(),
));
}
關於您的問題,是否手動將父母添加到孩子以便識別雙向關聯是正確的方法。 是的。
至於第二個問題。 似乎Doctrine無法說出,它需要在持久化到達元素之前先持久化到達,從而導致您面臨的null id問題。 您可以通過指定如下所示的表單的data_class
來解決此問題,以確保表單返回正確的元素:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => ElementArrivage::class,
));
}
即使那樣,您的實體也可能不受教義管理,因為您是手動創建它們的。 由於Symfony Form嘗試使用類的getter和setter,因此當Arrivage類具有此類setter時,它應該識別實體並也將其持久化:
public function setElementArrivages($elements)
{
foreach($elements as $element) {
$this->addElementArrivage($element); // the method from your example
}
}
您可能還必須堅持不指定實體,所以只需$em->persist();
而不是$em->persist($arrivage);
在您的控制器中;
如果所有這些都不起作用,請嘗試使用xdebug查看元素是否在實體管理器的工作單元中。 如果沒有,您可以隨時手動保留它們:
if ($form->isSubmitted() && $form->isValid()) {
$elements = $arrivage->getElementArrivages();
foreach ($elements as $element) {
$em->persist($element);
}
$em->persist($arrivage);
$em->flush();
}
當您必須手動控制像這樣的教義時,通常表明您正在做某事超出其想做的事情以及它在哪里表現良好。 您可能需要考慮重新組織域/表映射。
謝謝@dhrumann的合作對我非常有益,現在我知道doctrine:generate:crud僅提供了控制器的主要框架,而不是完全適合我情況的控制器。
因此,對於我的代碼中正確提到的data_class(由doctrine:generate:crud自動生成)
關於您的最后一個代碼段,我認為這不是邏輯,因為您試圖在持久化作為其自身父級的(Arrivage)之前持久化包含arrivage_id的(ElementsArrivage)。 因此,arrivage_id將為null,這將導致我認為的問題。 你確認嗎?
我采用的解決方案是:(請參閱//添加的塊)
public function newAction(Request $request){
$arrivage = new Arrivage();
$form = $this->createForm('AppBundle\Form\ArrivageType', $arrivage);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//Added Block Begiiiiiiin
$elementArrivages = $arrivage->getElementArrivages();
foreach( $elementArrivages as $elementArrivage){
$elementArrivage->setArrivage($arrivage);
}
//Added Block Ennnnnd
$em = $this->getDoctrine()->getManager();
$em->persist($arrivage);
$em->flush();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.