Skip to content

Add adders and remover callbacks #66

Open
@zmitic

Description

@zmitic

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions