问题
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