Description
I just upgraded to Symfony 2.7.10 and ran into the following problem:
Entities passed to the choice field must be managed. Maybe persist them in the entity manager?
#0 [internal function]: Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader->getIdValue(Object(Doctrine\Common\Collections\ArrayCollection))
#1 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php(164): call_user_func(Array, Object(Doctrine\Common\Collections\ArrayCollection))
#2 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php(151): Symfony\Component\Form\ChoiceList\ArrayChoiceList->getValuesForChoices(Array)
#3 [internal function]: Symfony\Component\Form\Extension\Core\Type\ChoiceType->Symfony\Component\Form\Extension\Core\Type\{closure}(Object(Symfony\Component\Form\FormEvent), 'form.pre_set_da...', Object(Symfony\Component\EventDispatcher\EventDispatcher))
#4 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php(158): call_user_func(Object(Closure), Object(Symfony\Component\Form\FormEvent), 'form.pre_set_da...', Object(Symfony\Component\EventDispatcher\EventDispatcher))
#5 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php(46): Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(Array, 'form.pre_set_da...', Object(Symfony\Component\Form\FormEvent))
#6 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php(43): Symfony\Component\EventDispatcher\EventDispatcher->dispatch('form.pre_set_da...', Object(Symfony\Component\Form\FormEvent))
#7 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php(342): Symfony\Component\EventDispatcher\ImmutableEventDispatcher->dispatch('form.pre_set_da...', Object(Symfony\Component\Form\FormEvent))
#8 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php(57): Symfony\Component\Form\Form->setData(Object(Doctrine\Common\Collections\ArrayCollection))
#9 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php(386): Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper->mapDataToForms(Object(CA\IndividualQuestionBundle\Entity\IndividualQuestionAnswer), Object(RecursiveIteratorIterator))
#10 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php(57): Symfony\Component\Form\Form->setData(Object(CA\IndividualQuestionBundle\Entity\IndividualQuestionAnswer))
#11 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php(386): Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper->mapDataToForms(Object(CA\QuestionnaireBundle\Entity\QuestionAnswer), Object(RecursiveIteratorIterator))
#12 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php(57): Symfony\Component\Form\Form->setData(Object(CA\QuestionnaireBundle\Entity\QuestionAnswer))
#13 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php(386): Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper->mapDataToForms(Object(Doctrine\Common\Collections\ArrayCollection), Object(RecursiveIteratorIterator))
#14 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php(57): Symfony\Component\Form\Form->setData(Object(Doctrine\Common\Collections\ArrayCollection))
#15 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php(386): Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper->mapDataToForms(Object(CA\ReviewBundle\Entity\Review), Object(RecursiveIteratorIterator))
#16 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php(478): Symfony\Component\Form\Form->setData(Object(CA\ReviewBundle\Entity\Review))
#17 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/FormBuilder.php(226): Symfony\Component\Form\Form->initialize()
#18 /var/www/review-analytics/symfony/vendor/symfony/symfony/src/Symfony/Component/Form/FormFactory.php(39): Symfony\Component\Form\FormBuilder->getForm()
Its caused by this field:
$field = $builder->create('individualQuestionOptions', 'entity', array(
'class' => IndividualQuestionOption::class,
'multiple' => false,
'expanded' => true,
'auto_initialize' => false,
'choices' => $question->getIndividualQuestionOptions(),
'translation_domain' => 'validators',
'empty_value' => false,
));
$field->addModelTransformer(new ChoiceToQuestionOptionTransformer());
The thing is that I'm using a OneToMany relation but in some cases only want the user to select one entity (hence 'multiple' => false
). I'm using a ModelTransformer then to transform the collection to one entity and vice versa:
class ChoiceToQuestionOptionTransformer implements DataTransformerInterface
{
public function transform($value)
{
if ($value instanceof Collection) {
return $value->first();
}
}
public function reverseTransform($value)
{
$col = new ArrayCollection();
if ($value != '') {
$col->add($value);
}
return $col;
}
}
This used to work fine with Symfony 2.7.9. Since this change it does not work anymore though:
a7f9831#diff-11ee91a32c601e8e1d509117556d53b3R149
Here the untransformed model data is used (which is an empty ArrayCollection initialized in the model) and obviously the collection itself is not managed. Which causes the Exception.
If I change it to this then it seems to work in my case:
$builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
$choiceList = $event->getForm()->getConfig()->getOption('choice_list');
$value = current($choiceList->getValuesForChoices(array($event->getForm()->getNormData())));
$event->setData((string) $value);
});
Not sure this is ok though. Is it correct to use the untransformed model data and not the norm data? Or do I have to adapt my code to not use a DataTransformer in this case?