Can't persist symfony collection with double embedded form

◇◆丶佛笑我妖孽 提交于 2020-01-17 07:05:34

问题


I receive the following error when trying to submit my form :

An exception occurred while executing 'INSERT INTO UserIngredientSupplier (quantity, cost, createdAt, updatedAt, unitId, organizationId, userIngredientId) VALUES (?, ?, ?, ?, ?, ?, ?)' with params [1000, 4.5, "2014-11-27 22:46:51", "2014-11-27 22:46:51", 4, 2, null]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Le champ 'userIngredientId' ne peut être vide (null)

I did not forget to put 'by_reference' => false, I did not forget the cascad={"persist"} on my entities and I also put the setters for both my entities User and UserIngredients like :

My post parameters are the following :

[
  userIngredients => [
    0 => [
      nickname => Blé, 
      name => Ebly® - 500 g, 
      quantityInStock => 5000, 
      unit => 4, 
      userIngredientSuppliers => [
        0 => [
          quantity => 1000, 
          cost => 4.5, 
          unit => 4, 
          userSupplier => 2
        ]
      ]
    ], 
    1 => [
      nickname => Lait, 
      name => Lait Viva, 
      quantityInStock => 4000, 
      unit => 4
    ]
  ], 
  submit => , 
  _token => PRktvw2sSa7lBiZ9DIIAzhzaxg4ysWGyAazbZHPOnMA
]

What I am missing ? What would the UserIngredientId not be persisted ? Does it not come with the UserIngredientSupplierType being called from the UserIngredientType ?

Controller:

    /**
     * Displays a form to create a new FoodAnalyticsUserIngredient entity.
     *
     * @Route("/ing1", name="ing1")
     * @Method({"PUT","GET"})
     * @Template(":FoodAnalytics/UserIngredient:ing1.html.twig")
     * @param Request $request
     * @return array|SymfonyComponentHttpFoundationRedirectResponse
     */
    public function parameterIng1Action(Request $request)
    {
        $userIngredientManager = $this->get('user_ingredient_manager');
        $ingredient = $this->getDoctrine()->getRepository('AppBundle:FoodAnalyticsUserIngredient')->findOneById(5);
        $parameterUserIngredientsForm = $userIngredientManager->getParameterIng1Form($ingredient);


        if ($request->getMethod()=='PUT')
        {
            $formManager = $this->get('form_manager');

            if ($formManager->handleRequestAndFlush($parameterUserIngredientsForm,$ingredient))
            {
                return $this->redirect($this->generateUrl('my_ingredients').'/parameter_selection');
            }
        }

        return array(
            'parameter_user_ingredients_form' => $parameterUserIngredientsForm->createView()
        );
    }


    /**
     * @return SymfonyComponentFormForm|SymfonyComponentFormFormInterface
     */
    public function getParameterIng1Form($ingredient)
    {
        $unitRepository = $this->em->getRepository('AppBundle:FoodAnalyticsUnit');

        $userIngredientsForm = $this->formManager->createForm(
            new UserIngredientType($unitRepository),
            $ingredient,
            'PUT',
            'ing1',
            null,
            'Enregistrer les changements'
        );

        return $userIngredientsForm;
    }

Form type:

<?php
namespace AppBundleFormFoodAnalytics;

use AppBundleFormEventListenerAddUnitFieldSubscriber;
use AppBundleRepositoryFoodAnalyticsUnitRepository;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolverInterface;

class UserIngredientType extends AbstractType
{

    protected $unitRepository;

    public function __construct(UnitRepository $unitRepository)
    {
        $this->unitRepository = $unitRepository;
    }

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nickname', null, array(
                    'label'=>'Nom raccourci',
                    'attr'=>array(
                        'data-toggle'=>"tooltip",
                        'data-placement'=>"top",
                        'title'=>"Le nom raccourci peut être utilisé dans les recettes. Il doit être unique",
                        'class' => 'input-sm'
                    )))
            ->add('name', null, array(
                    'label'=>'Nom complet',
                    'attr'=>array(
                        'data-toggle'=>"tooltip",
                        'data-placement'=>"top",
                        'title'=>"Le nom complet peut être utilisé dans les recettes. Il doit être unique.",
                        'class' => 'input-sm'
                    )))
            ->add('quantityInStock', null, array(
                    'label'=>'Stock',
                    'attr'=>array(
                        'data-toggle'=>"tooltip",
                        'data-placement'=>"top",
                        'title'=>"Indiquez l'état de votre stock pour gérer vos commandes",
                        'class' => 'input-sm'
                    )))
            ->add('userIngredientSuppliers', 'collection', array(
                    'type' => new UserIngredientSupplierType($this->unitRepository),
                    'allow_add' => true,
                    'allow_delete' => true,
                    'by_reference' => false,
                ))
        ;

        $builder->addEventSubscriber(new AddUnitFieldSubscriber($this->unitRepository));
    }

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

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

Entity:

<?php
namespace AppBundleEntityFoodAnalytics;
use AppBundleModelBaseCategoryClass;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineORMMapping AS ORM;
use GedmoMappingAnnotation as Gedmo;

/**
 * @ORMEntity(repositoryClass="AppBundleRepositoryFoodAnalyticsUserIngredientRepository")
 * @GedmoTree(type="nested")
 */
class UserIngredient extends BaseCategoryClass
{
    /**
     * @ORMId
     * @ORMColumn(type="integer", length=11)
     * @ORMGeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORMColumn(type="boolean", nullable=true)
     */
    private $isImported;

    /**
     * @ORMColumn(type="string", length=100, nullable=false)
     */
    protected $name;

    /**
     * @ORMColumn(type="string", length=50, nullable=true)
     */
    private $nickname;

    /**
     * @ORMColumn(type="decimal", precision=10, scale=2, nullable=true)
     */
    private $quantityInStock;

    /**
     * @ORMManyToOne(targetEntity="AppBundleEntityMarketPlaceProduct", inversedBy="userIngredients")
     * @ORMJoinColumn(name="productId", referencedColumnName="id", nullable=false, onDelete="cascade")
     */
    private $product;

    /**
     * @GedmoBlameable(on="create")
     * @ORMManyToOne(targetEntity="AppBundleEntityUserUser", inversedBy="userIngredients")
     * @ORMJoinColumn(name="userId", referencedColumnName="id", nullable=false, onDelete="cascade")
     */
    private $user;

    /**
     * @ORMManyToOne(targetEntity="AppBundleEntityFoodAnalyticsUnit")
     * @ORMJoinColumn(name="unitId", referencedColumnName="id", nullable=false, onDelete="restrict")
     */
    private $unit;

    /**
     * @ORMOneToMany(targetEntity="AppBundleEntityFoodAnalyticsUserRecipeIngredient", mappedBy="userIngredient")
     */
    protected $userRecipeIngredients;

    /**
     * @ORMOneToMany(targetEntity="AppBundleEntityFoodAnalyticsUserIngredientSupplier", mappedBy="userIngredient", cascade={"persist"})
     */
    protected $userIngredientSuppliers;

    /**
     * @GedmoTreeParent
     * @ORMManyToOne(targetEntity="AppBundleEntityFoodAnalyticsUserIngredient", inversedBy="children")
     * @ORMJoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $parent;

    /**
     * @ORMOneToMany(targetEntity="AppBundleEntityFoodAnalyticsUserIngredient", mappedBy="parent", cascade={"persist"})
     */
    protected $children;


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


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

    /**
     * Set name
     *
     * @param string $name
     *
     * @return UserIngredient
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Set nickname
     *
     * @param string $nickname
     *
     * @return UserIngredient
     */
    public function setNickname($nickname)
    {
        $this->nickname = $nickname;

        return $this;
    }

    /**
     * Get nickname
     *
     * @return string
     */
    public function getNickname()
    {
        return $this->nickname;
    }

    /**
     * Set quantityInStock
     *
     * @param float $quantityInStock
     *
     * @return UserIngredient
     */
    public function setQuantityInStock($quantityInStock)
    {
        $this->quantityInStock = $quantityInStock;

        return $this;
    }

    /**
     * Get quantityInStock
     *
     * @return string
     */
    public function getQuantityInStock()
    {
        return $this->quantityInStock;
    }

    /**
     * Set product
     *
     * @param AppBundleEntityMarketPlaceProduct $product
     *
     * @return UserIngredient
     */
    public function setProduct(AppBundleEntityMarketPlaceProduct $product)
    {
        $this->product = $product;

        return $this;
    }

    /**
     * Get product
     *
     * @return AppBundleEntityMarketPlaceProduct
     */
    public function getProduct()
    {
        return $this->product;
    }

    /**
     * Set user
     *
     * @param AppBundleEntityUserUser $user
     *
     * @return UserIngredient
     */
    public function setUser(AppBundleEntityUserUser $user)
    {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return AppBundleEntityUserUser
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * Set unit
     *
     * @param AppBundleEntityFoodAnalyticsUnit $unit
     *
     * @return UserIngredient
     */
    public function setUnit(AppBundleEntityFoodAnalyticsUnit $unit)
    {
        $this->unit = $unit;

        return $this;
    }

    /**
     * Get unit
     *
     * @return AppBundleEntityFoodAnalyticsUnit
     */
    public function getUnit()
    {
        return $this->unit;
    }

    /**
     * Set isImported
     *
     * @param boolean $isImported
     *
     * @return UserIngredient
     */
    public function setIsImported($isImported)
    {
        $this->isImported = $isImported;

        return $this;
    }

    /**
     * Get isImported
     *
     * @return boolean
     */
    public function getIsImported()
    {
        return $this->isImported;
    }

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->userRecipeIngredients = new DoctrineCommonCollectionsArrayCollection();
    }

    /**
     * Add userRecipeIngredient
     *
     * @param AppBundleEntityFoodAnalyticsUserRecipeIngredient $userRecipeIngredient
     *
     * @return UserIngredient
     */
    public function addUserRecipeIngredient(AppBundleEntityFoodAnalyticsUserRecipeIngredient $userRecipeIngredient)
    {
        $this->userRecipeIngredients[] = $userRecipeIngredient;

        return $this;
    }

    /**
     * Remove userRecipeIngredient
     *
     * @param AppBundleEntityFoodAnalyticsUserRecipeIngredient $userRecipeIngredient
     */
    public function removeUserRecipeIngredient(AppBundleEntityFoodAnalyticsUserRecipeIngredient $userRecipeIngredient)
    {
        $this->userRecipeIngredients->removeElement($userRecipeIngredient);
    }

    /**
     * Get userRecipeIngredients
     *
     * @return DoctrineCommonCollectionsCollection
     */
    public function getUserRecipeIngredients()
    {
        return $this->userRecipeIngredients;
    }

    /**
     * Add userIngredientSupplier
     *
     * @param AppBundleEntityFoodAnalyticsUserIngredientSupplier $userIngredientSupplier
     *
     * @return UserIngredient
     */
    public function addUserIngredientSupplier(AppBundleEntityFoodAnalyticsUserIngredientSupplier $userIngredientSupplier)
    {
        //Needed cause the setter wouldn't be called even with by_reference = false
//        $userIngredientSupplier->setUserIngredient($this);

        $this->userIngredientSuppliers[] = $userIngredientSupplier;

        return $this;
    }

    /**
     * Remove userIngredientSupplier
     *
     * @param AppBundleEntityFoodAnalyticsUserIngredientSupplier $userIngredientSupplier
     */
    public function removeUserIngredientSupplier(AppBundleEntityFoodAnalyticsUserIngredientSupplier $userIngredientSupplier)
    {
        $this->userIngredientSuppliers->removeElement($userIngredientSupplier);
    }

    /**
     * Get userIngredientSuppliers
     *
     * @return DoctrineCommonCollectionsCollection
     */
    public function getUserIngredientSuppliers()
    {
        return $this->userIngredientSuppliers;
    }

    /**
     * Set userIngredientSuppliers
     *
     * @param ArrayCollection $userIngredientSuppliers
     * @return DoctrineCommonCollectionsCollection
     */
    public function setUserIngredientSuppliers(ArrayCollection $userIngredientSuppliers)
    {
        /** @var $userIngredientSupplier UserIngredientSupplier */
        foreach ($userIngredientSuppliers as $userIngredientSupplier)
        {
            $userIngredientSupplier->setUserIngredient($this);
        }

        exit(var_dump($userIngredientSuppliers));

        $this->userIngredientSuppliers=$userIngredientSuppliers;
    }
}

PHP:

<?php
namespace AppBundleEntityFoodAnalytics;
use DoctrineORMMapping AS ORM;
use GedmoMappingAnnotation as Gedmo;
use GedmoTimestampableTraitsTimestampableEntity;

/**
 * @ORMEntity(repositoryClass="AppBundleRepositoryFoodAnalyticsUserIngredientSupplierRepository")
 */
class UserIngredientSupplier
{
    use TimestampableEntity;

    /**
     * @ORMId
     * @ORMColumn(type="integer", length=11)
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORMColumn(type="decimal", precision=10, scale=2, nullable=true)
     */
    private $quantity;

    /**
     * @ORMColumn(type="decimal", precision=10, scale=2, nullable=true)
     */
    private $cost;

    /**
     * @ORMManyToOne(targetEntity="AppBundleEntityFoodAnalyticsUnit")
     * @ORMJoinColumn(name="unitId", referencedColumnName="id", nullable=false, onDelete="restrict")
     */
    private $unit;

    /**
     * @ORMManyToOne(targetEntity="AppBundleEntityFoodAnalyticsUserSupplier", inversedBy="userIngredientSuppliers")
     * @ORMJoinColumn(name="organizationId", referencedColumnName="id", nullable=true, onDelete="cascade")
     */
    private $userSupplier;

    /**
     * @ORMManyToOne(targetEntity="AppBundleEntityFoodAnalyticsUserIngredient", inversedBy="userIngredientSuppliers")
     * @ORMJoinColumn(name="userIngredientId", referencedColumnName="id", nullable=false, onDelete="cascade")
     */
    private $userIngredient;


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

    /**
     * Set quantity
     *
     * @param string $quantity
     *
     * @return UserIngredientSupplier
     */
    public function setQuantity($quantity)
    {
        $this->quantity = $quantity;

        return $this;
    }

    /**
     * Get quantity
     *
     * @return string
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * Set cost
     *
     * @param string $cost
     *
     * @return UserIngredientSupplier
     */
    public function setCost($cost)
    {
        $this->cost = $cost;

        return $this;
    }

    /**
     * Get cost
     *
     * @return string
     */
    public function getCost()
    {
        return $this->cost;
    }

    /**
     * Set userSupplier
     *
     * @param AppBundleEntityFoodAnalyticsUserSupplier $userSupplier
     *
     * @return UserIngredientSupplier
     */
    public function setUserSupplier(AppBundleEntityFoodAnalyticsUserSupplier $userSupplier = null)
    {
        $this->userSupplier = $userSupplier;

        return $this;
    }

    /**
     * Get userSupplier
     *
     * @return AppBundleEntityFoodAnalyticsUserSupplier
     */
    public function getUserSupplier()
    {
        return $this->userSupplier;
    }

    /**
     * Set userIngredient
     *
     * @param AppBundleEntityFoodAnalyticsUserIngredient $userIngredient
     *
     * @return UserIngredientSupplier
     */
    public function setUserIngredient(AppBundleEntityFoodAnalyticsUserIngredient $userIngredient)
    {
        $this->userIngredient = $userIngredient;

        return $this;
    }

    /**
     * Get userIngredient
     *
     * @return AppBundleEntityFoodAnalyticsUserIngredient
     */
    public function getUserIngredient()
    {
        return $this->userIngredient;
    }

    /**
     * Set unit
     *
     * @param AppBundleEntityFoodAnalyticsUnit $unit
     *
     * @return UserIngredientSupplier
     */
    public function setUnit(AppBundleEntityFoodAnalyticsUnit $unit)
    {
        $this->unit = $unit;

        return $this;
    }

    /**
     * Get unit
     *
     * @return AppBundleEntityFoodAnalyticsUnit
     */
    public function getUnit()
    {
        return $this->unit;
    }
}

来源:https://stackoverflow.com/questions/27179260/cant-persist-symfony-collection-with-double-embedded-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!