-
-
Notifications
You must be signed in to change notification settings - Fork 413
[LiveCollection] LiveCollectionType may reuse removed Doctrine entity when adding a new item due to index reuse #3371
Description
Description
I'm encountering an issue when using LiveComponent + LiveCollectionType with a Doctrine Collection.
The problem seems related to how $formValues indexes are handled when removing and adding items.
Context
Symfony UX LiveComponent version: 2.31
Symfony version: 7.4.1
Doctrine/ORM version: 3.5.7
PHP version: 8.4
I'm using:
- Symfony UX LiveComponent
LiveCollectionType- A Doctrine collection inside a form.
Current behaviour
Suppose the collection initially contains 3 elements.
Indexes in $formValues are:
0, 1, 2
If I remove the last element using the remove action from LiveCollectionTrait, index 2 is removed and the array keys become:
0, 1
Then, when adding a new element via the add action, the following code is executed in LiveCollectionTrait -> addCollectionItem (line 36) :
$index = [] !== $data ? max(array_keys($data)) + 1 : 0;In this case:
max index = 1
new index = 2
So the new item is inserted at index 2.
The issue
Because index 2 previously existed and was mapped to a Doctrine entity, the newly added entry ends up being mapped back to the previously removed entity instead of creating a new one.
This leads to unexpected behavior where:
- the removed entity appears again
- a new object is not actually created
Expected behaviour
When adding a new element after a removal, a new entry should always be created, without reusing a previously removed reference.
Possible cause
The issue seems to be that the index used in $formValues is derived from the current max key, which may correspond to a previously removed entry.
This becomes problematic when working with Doctrine collections and form data mapping.
Possible solution ideas
The workaround I've found is :
#[LiveProp]
public int $maxInitialKey = 0;
#[PostMount]
public function postMount(): void
{
$this->maxInitialKey = max($this->entity->collection->getKeys());
}
#[LiveAction]
public function addCollectionItem(PropertyAccessorInterface $propertyAccessor, #[LiveArg] string $name): void
{
$key = $this->maxInitialKey + 1;
if (array_key_exists($key, $this->formValues['collection'])) {
$key = max(array_keys($this->formValues['collection'])) + 1;
}
$this->formValues['collection'][$key] = [];
}Question
Is this the expected behavior of LiveCollectionType, or could this be considered a bug when working with Doctrine collections?