问题
I have a Symfony OrderType
form attached to an Order
object. This Order
object has an items
property which contains an ArrayCollection
of OrderItem
objects. These OrderItem
objects each contain product
and quantity
properties. The product
property is linked to a Product
object. Each OrderItem
is associated to an OrderItemType
which is part of the CollectionType
associated to the Order
items
property.
To make a long story short, here is the code (very simplified, with minimal properties and no doctrine annotations):
Please note that everything basically works, I'm not looking for an error in this code :)
Order class
class Order {
private $id;
private $items;// ArrayCollection of OrderItem
}
Order item class
class OrderItem {
private $id;
private $product;// Product object
private $quantity;// int
}
Order form
class OrderType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('items', CollectionType::class, array(
'by_reference' => false,
'entry_type' => OrderItemType::class,
'allow_add' => true,
'allow_delete' => true
));
}
}
Order item form
class OrderItemType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('product', EntityType::class, array(
'class' => 'AppBundle\Entity\Product',
'choice_label' => 'id'
))
->add('quantity', NumberType::class)
}
}
Of course, the user can add and delete lines in an order which creates, edits and removes lines appropriately. Well almost...
If I remove the last line of the order and create a new line, Symfony thinks that the new line is actually a modification of the old one. Of course, there is no way for Symfony to know that this line is not the old one.
So I added an id
field to my OrderItemType
. But of course, Symfony cannot set the id
on submit because there is no setId
method in OrderItem
(and that's normal because setting the id
of an object manually is a bad idea).
Well that's where I'm stuck. I guess I could set the id
field as mapped: false
and implement custom logic on the controller to get rid of the old item that was deleted when its id
does not appear in the posted values and create a new OrderItem
for the item that has an empty id
, but this seems like ugly hacking to me and I wonder if I'm not completely missing something as this looks like a very basic problem.
So does Symfony have a built-in way to recognize the difference between deletion+creation and edition in a CollectionType
form? Am I completely missing something? Is the cake a lie?
Edit
I know that my code is not complete, but I want to focus on the problem at hand. To put in another way:
- The user creates two lines in the order for a client that wants 3 productA and 2 productB.
- The user saves the order (Symfony creates 2
OrderItem
objects with ID 1 and 2 in the database) - The client calls again and wants 5 productC instead of the 2 productB.
- The user deletes line 2 (2 productB) and adds a new line (5 productC).
Here, Symfony changes the OrderItem
with ID #2 by assigning the new product (productC) and quantity (5). But I would like Symfony to delete OrderItem
#2 and create a new OrderItem
with ID 3.
I hope that's a little bit more clear.
回答1:
I know you haven't added your Doctrine annotations yet, but it's related to the Id problem you are describing. Normally you auto generate an ID, so there is no 'setter', but there is a 'getter'.
So you would have something like this:
class OrderItem {
...
/**
* @ORM\Id
* @ORM\Column(name="order_item_id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $order_item_id;
Yes, your $quantity value should be an 'int', but it doesn't really matter. I'm just making you aware that you can't have half a quantity.
来源:https://stackoverflow.com/questions/38333413/symfony-collectiontype-regards-deletioncreation-as-a-modification-of-an-item