Description
When dealing with collections, using write_property_path
can be problematic when dealing with non-direct relations.
Simple example; please note I am using new arrow function for readibility, recent github changes for code blocks are problematic:
Lets say we have Category<->Product many2many but with association class. But our form don't need to display assoc class, it can be much simpler:
// CategoryType
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('products', EntityType::class, ...options...];
}
And Category entity:
public function getProducts(): array
{
return $this->association
->map(fn(CategoryProductAssociation $assoc) => $assoc->getProduct())
->toArray();
}
public function addProduct(Product $product): void
{
$this->assoc->add(
new ProductCategoryAssociation($this, $product,... some extra param...)
);
}
public function removeProduct(Product $product): void
{
if ($assoc = $this->findAssociationToProduct($product)) {
$this->association->removeElement($assoc);
}
}
But when there is only setProducts(array $products)
'write_property_path' => fn($category, array $products) => $category->setProducts($products)
code would be much more complex. User would need to manually compare existing vs new values, something that Symfony already does perfectly.
Usage
New options would be:
$builder->add('products', EntityType::class, [
'read_property_path' => fn(Category $category) => $category->getProducts(),
// removed typehints for readibility
'adder' => fn($category, $product) => $category->addProduct($product),
'remover' => fn($category, $product) => $category->removeProduct($product),
]);
If adder
and remover
are set, then write_property_path
is not required.
This has more usages when there is extra param needed, something I really need in my current app and the reason why I have to use DTO. If interested, I will put the problem here.
But in short; I have m2m relation between Client and CustomValue. CustomValue has discriminator string column type
.
Entire ClientType form is made of 11 pages (flow bundle) and most of fields are working with that m2m relation but depend on value type
column.
So for each value of type
, I would need to write getter, adder and remover methods and make my entity totally unreadable.
With this RFC, I could change that to simple:
// ClientType.php
'read_property_path' => fn($client) => $client->getValuesOfType('xxx'),
'adder' => fn($client, $value) => $client->addValueOfType('xxx', $value),
'remover' => fn($client, $value) => $client->removeValueOfType('xxx', $value),
This way, I would need only 3 methods.