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)