8000 [Form] ChoiceType error since update to 2.7.10 · Issue #18173 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
[Form] ChoiceType error since update to 2.7.10  #18173
Closed
@dmaicher

Description

@dmaicher

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?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0