Я работаю с Symfony 3.4 lts , и у меня возникает проблема с Встроенными формами сбора персистентность.
В этом выпуске требуется Symfony Expert .. Описание где-то кажется длинным, но 80% кода генерируется автоматически с помощью команд Symofny CLI по умолчанию.
Я эксперт по сокращению, так что вы обнаружите, что мое описание простое и педагогическое,
Мои 3 сущности описаны с помощью этого простого UML Diagram Class
Код на французском языке, поэтому Arrival - это Arrivage, продукт - Produit, а промежуточным объектом ArrivalElement - ElementArrivage.
Сущность: Arrivage.php (Прибытие на английском языке)
/**
* 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
Entity: ElementArrivage (промежуточный объект, созданный для отношения «Многие ко многим» с дополнительным полем)
/**
* 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.php:
/**
* 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
Форма: ArrivageType.php:
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
)
))
;
}/**
Форма: ElementArrivage.php:
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,
));
;
}/*
Итак, моя основная сущность - это прибытие, я должен создать прибытие, а остальное должно остаться на Каскаде, так что мне нужно создать контроллер только для сущности прибытия
ArrivageController:
все еще чисто после генерации грубого учения
Вид:
Я использовал технику документации (прототип), чтобы позволить создать новый 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
Я решил эту проблему, добавив строку в Entity Arrivage в методе:
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
Второй вопрос: я понятия не имею о решении, но когда я попытался изменить контроллер с помощью этой строки, проблема исчезла, но это не решение, потому что в этом случае ElementArrivage будет исправлено на два:
ArrivageController:
/**
* 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(),
));
}