简体   繁体   中英

Symfony array as Form Collection

I have been stuck with a problem in Symfony for days, and can't find anything on google.

I have two tables.

Account:

AppBundle\Entity\Account:
type: entity
fields:
    name:
        type: string
        nullable: true
        length: 255
oneToMany:
    towns:
        targetEntity: AppBundle\Entity\Town
        mappedBy: owner
        cascade: ['persist']

Town:

AppBundle\Entity\Town:
type: entity
fields:
    name:
        type: string
        nullable: true
        length: 255
manyToOne:
    owner:
        targetEntity: AppBundle\Entity\Account
        inversedBy: towns

And I have an array with names:

$names = ['New York','Berlin'];

I want a form in which the user can check a name from the array (Check boxes). When the user checks 'New York' and submits the form, I want a new entity Town with 'New York' in the name field. If the user unchecks 'New York', I want the entity removed.

So far I tried it with EntityType , CollectionType , and ChoiceType . The Best I can get is with ChoiceType.

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('towns', ChoiceType::class,
            [
                'choices' =>
                    [
                        new Town('New York'),
                        new Town('Berlin'),
                    ],
                'choice_label' => function (Town $town, $key, $index) {
                    return $town->getName();
                },
                'choice_value' => function (Town $town) {
                    return $town->getName();
                },
                'expanded' => TRUE,
                'multiple' => TRUE,
                'required' => FALSE,
            ]
        );
}

But it will add a new entity every time the user submits the form for any town that is checked and it does not remove the non checked one...

Don't use an array, store the towns in the database.
Then set the towns field type to EntityType .

->add(
    'towns',
    EntityType::class,
    [
        'class' => Town::class,
        'multiple' => true,
        'expanded' => true,
        'required' => false,
    ]
)

Add this method to your Town class to display the name automatically everywhere it has to be converted to string:

/**
 * @return string
 */
public function __toString()
{
    return $this->name;
}

If the idea with the array was to filter the choices displayed to choose towns, you could use it in the query_builder option:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $names = ['New York', 'Berlin']; // Or pass it from the controller in $options

    $builder
        ->add('towns',
            EntityType::class,
            [
                'class' => Town::class,
                'query_builder' => function (EntityRepository $er) use ($names) {
                    return $er->createQueryBuilder('town')
                        ->where('town.name IN (:names)')
                        ->setParameter('names', $names);
                },
                'multiple' => true,
                'expanded' => true,
                'required' => false,
            ]
        );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM