Почему не сопоставленная доктринам ArrayCollection не инициализируется? - PullRequest
0 голосов
/ 27 марта 2019

My Setup - это приложение Symfony 3.4 с типичным ManyToMany - отношением с дополнительными полями, что-то вроде этого:

Entity Article
Entity Specialty
Entity ArticleSpecialtyRelation

В Form для Article я хотел, чтобы это выглядело так, как если бы это было ManyToMany -отношение, отображаемое как EntityType с multiple=true и expanded=true, поэтому все записи Specialty отображаются в виде флажков.

Чтобы добиться этого, я создал не отображенное в orm свойство specialties, которое представляет собой ArrayCollection, инициализируется в Конструкторе и имеет Getter, Adder и 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);
}

Это свойство используется для визуализации Specialty сущности в виде флажков:

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

Чтобы заполнить его данными из SpecialtyRelation, я добавил 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());
            }
        });

Используемый метод получения $artikel просто перебирает $article->getArtikelSpecialties и возвращает коллекцию Specialty.

Все работает до отправки. Поскольку поле формы равно mapped=true, где-то в handleRequest($form), где объект гидратируется данными формы, он взрывается, когда вызывается сумматор для $specialty:

Call to a member function add() on null

Потому что, как я только что узнал, Doctrine никогда не вызывает Constructor и, очевидно, инициализирует все ORM- ArrayCollections, но не ArrayCollection для неотображенного свойства specialties -

Конечно, я могу проверить, инициализирован ли ArrayCollection в Adder и Remover, и инициализировать его там, если он нулевой, но это выглядит немного хакерским в уже хотя бы хакерской настройке, и мне интересно, мои настройки совершенно глупы, тем более что я не нашел никого, кто пытался бы сделать это (или получить проблемы с этим) здесь или в другом месте.

Есть ли лучшее решение для этого или я должен просто проверить ArrayCollection в Adder и Remover и жить долго и счастливо? Кроме того, просто любопытно, есть ли другой способ инициализации ArrayCollection?

P.S. Если в именах есть опечатки, это потому, что я перевел имена на английский.

Частичная трассировка стека

Symfony \ Component \ Debug \ Exception \ FatalThrowableError: вызов функция-член add () в null

в src / Test / Bundle / TestBundle / Entity / Article.php: 312 в Test \ Bundle \ TestBundle \ Entity \ article-> addSpecialties (объект (специальность)) (Поставщик / Symfony / Symfony / SRC / Symfony / Компонент / PropertyAccess / PropertyAccessor.php: 674) в Symfony \ Component \ PropertyAccess \ PropertyAccessor-> WriteCollection (массив (объект (статья), объект (статья)), 'специальности', объект (ArrayCollection), 'addSpecialties', 'removeSpecialties') (Поставщик / Symfony / Symfony / SRC / Symfony / Компонент / PropertyAccess / PropertyAccessor.php: 622) в Symfony \ Component \ PropertyAccess \ PropertyAccessor-> WriteProperty (массив (объект (статья), объект (статья)), 'специальности', объект (ArrayCollection)) (Поставщик / Symfony / Symfony / SRC / Symfony / Компонент / PropertyAccess / PropertyAccessor.php: 216) в Symfony \ Component \ PropertyAccess \ PropertyAccessor-> SetValue (объект (статья), объект (PropertyPath), объект (ArrayCollection)) (Поставщик / Symfony / Symfony / SRC / Symfony / Компонент / Форма / расширение / Ядро / DataMapper / PropertyPathMapper.php: 86) в Symfony \ Component \ Form \ Extension \ Ядро \ DataMapper \ PropertyPathMapper-> mapFormsToData (объект (RecursiveIteratorIterator), объект (статья)) (vendor / symfony / symfony / src / Symfony / Component / Form / Form.php: 636) в Symfony \ Component \ Form \ Form-> submit (array (), true) (Поставщик / Symfony / Symfony / SRC / Symfony / Компонент / Форма / form.php: 580)

...