1

My Setup is a Symfony 3.4 App with the typical 'ManyToMany'-Relation with additional fields, something like this:

Entity Article
Entity Specialty
Entity ArticleSpecialtyRelation

In a Form for an Article i wanted it to look like as if it were a ManyToMany-Relation rendered as an EntityType with multiple=true and expanded=true, so all entries of Specialty are rendered as checkboxes.

To achieve that i created a non orm-mapped property specialties that is an ArrayCollection, gets initialized in the Constructor and has a Getter, Adder and Remover.

 /**
 *
 * @var ArrayCollection;
 * 
 */
 protected $specialties;

public function __construct()
    {
        $this->specialties = new ArrayCollection();
    }

 /**
 * @return Collection|Specialty[]
 */
public function getSpecialties()
{
    return $this->specialties;
}

/**
 * @param Specialty $specialties
 */
public function addSpecialties(Specialty $specialties)
{
    $this->specialties->add($specialties);

}

/**
 * @param Specialty $specialties
 */
public function removeSpecialties(Specialty $specialties)
{
    $this->specialties->removeElement($specialties);
}

This property is used to render the Specialty Entity as checkboxes:

add('specialties', EntityType::class,array(
            'class' => Specialty::class,
            'expanded'=>true,
            'multiple'=>true,
            'label'=>'Specialties',
            'required' => false,
            'mapped'=>true,
        ));

To populate it with the data from SpecialtyRelation i added a PreSetData Formevent:

 $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $form = $event->getForm();
            $article = $event->getData();

            if ($article instanceof Article) {
                $form->get('specialties')->setData($article->getUsedSpecialties());
            }
        });

The used Getter of $artikel just iterates over $article->getArtikelSpecialties and returns a collection of Specialty.

It all works until the submit. Because the formfield is mapped=true, somewhere in handleRequest($form) where the entity is hydrated with the form data, it explodes when the Adder for $specialty is called:

Call to a member function add() on null

Because as i just learned, the Constructor is never called by Doctrine and obviously initializes all ORM-ArrayCollections but not the ArrayCollection for the non-mapped property specialties -

Of course I can check if the ArrayCollection is initialized in the Adder and Remover and initialize it there if it is null, but that just feels a bit hacky in a already at least hacky-felt setup and i am wondering if my setup is completely stupid, especially since i didn't find anybody trying to do that (or getting problems with that) on here or elsewhere.

Is there a better solution to this or should i just check the ArrayCollection in Adder and Remover and live happily ever after? Also, just curious, is there any other way to initialize the ArrayCollection?

P.S. If there are typos in the names it's because i translated the names into english.

Partial Stacktrace

Symfony\Component\Debug\Exception\FatalThrowableError: Call to a member function add() on null

at src/Test/Bundle/TestBundle/Entity/Article.php:312 at Test\Bundle\TestBundle\Entity\Article->addSpecialties(object(Specialty)) (vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php:674) at Symfony\Component\PropertyAccess\PropertyAccessor->writeCollection(array(object(Article), object(Article)), 'specialties', object(ArrayCollection), 'addSpecialties', 'removeSpecialties') (vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php:622) at Symfony\Component\PropertyAccess\PropertyAccessor->writeProperty(array(object(Article), object(Article)), 'specialties', object(ArrayCollection)) (vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php:216) at Symfony\Component\PropertyAccess\PropertyAccessor->setValue(object(Article), object(PropertyPath), object(ArrayCollection)) (vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php:86) at Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper->mapFormsToData(object(RecursiveIteratorIterator), object(Article)) (vendor/symfony/symfony/src/Symfony/Component/Form/Form.php:636) at Symfony\Component\Form\Form->submit(array(), true) (vendor/symfony/symfony/src/Symfony/Component/Form/Form.php:580)

  • `it explodes when the Adder for $specialty is called` mind that by phrasing it like that your question could also auto-implode. Rather add the exception trace in your question. – β.εηοιτ.βε Mar 26 '19 at 21:19
  • 1
    Thanks! I do mind of course :) and have added the exact error and a partial stacktrace with the interesting bit. – Benjamin Kozlowski Mar 26 '19 at 21:40

0 Answers0