Skip to content
Advertisement

Symfony: Expected argument of type “?DoctrineCommonCollectionsCollection”, “array” given at property path

i have a entity called DynamicForm, which looks like this:

<?php

namespace AppEntityProductDynamicForm;

use DoctrineCommonCollectionsCollection;
use DoctrineORMMapping as ORM;
use DoctrineORMMappingEntity;

/**
 * Class DynamicForm
 * @package AppEntityProduct
 *
 * @Entity
 * @ORMTable(name="product_dynamic_form")
 */
class DynamicForm
{
    /**
     * @ORMId()
     * @ORMGeneratedValue()
     * @ORMColumn(name="id", type="integer", unique=true, nullable=false)
     */
    private ?int $id = null;

    /**
     * @ORMOneToMany(targetEntity="AppEntityProductDynamicFormComponentText", mappedBy="dynamicForm")
     * @ORMJoinColumn(name="component_text_id", referencedColumnName="id")
     */
    private ?Collection $textComponents;

    /**
     * @return Collection|null
     */
    public function getTextComponents(): ?Collection
    {
        return $this->textComponents;
    }

    /**
     * @param Collection|null $textComponents
     *
     * @return DynamicForm
     */
    public function setTextComponents(?Collection $textComponents): DynamicForm
    {
        $this->textComponents = $textComponents;

        return $this;
    }
}

Also i created a related type for it – DynamicFormType:

<?php

namespace AppTypeProductDynamicForm;

use AppEntityProductDynamicFormDynamicForm;
use AppTypeProductDynamicFormComponentTextType;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormExtensionCoreTypeCollectionType;
use SymfonyComponentFormExtensionCoreTypeSubmitType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolver;

class DynamicFormType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('textComponents', CollectionType::class, [
                'entry_type'    => TextType::class,
                'entry_options' => ['label' => false],
                'allow_add'     => true,
                'allow_delete'  => true,
                'label'         => ' '
            ])
            ->add('submit', SubmitType::class, [
                'label' => 'form.basic.save'
            ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefault('data_class', DynamicForm::class);
    }
}

The TextType entry type class from the namespace AppTypeProductDynamicFormComponentTextType looks like this:

<?php

namespace AppTypeProductDynamicFormComponent;

use AppEntityProductDynamicFormComponentText;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormExtensionCoreType as FormType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolver;
use SymfonyContractsTranslationTranslatorInterface;

class TextType extends AbstractType
{
    private TranslatorInterface $translator;

    /**
     * TextType constructor.
     *
     * @param TranslatorInterface $translator
     */
    public function __construct(TranslatorInterface $translator)
    {
        $this->translator = $translator;
    }

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('label', FormTypeTextType::class, [
                'required'           => true,
                'translation_domain' => 'wedding',
                'label'              => 'setting.form.dynamic_by_user.query_to_guest'
            ])
            ->add('type', FormTypeChoiceType::class, [
                'required'                  => true,
                'translation_domain'        => 'wedding',
                'label'                     => 'setting.form.dynamic_by_user.select_type',
                'attr'                      => [
                    'class'                       => 'enriched',
                    'data-search-placeholder'     => $this->translator->trans('select.search'),
                    'data-search-no-results-text' => $this->translator->trans('select.search_no_results_found')
                ],
                'choice_translation_domain' => 'wedding',
                'choices'                   => [
                    'setting.form.dynamic_by_user.type_text'     => Text::TYPE_TEXT_FIELD,
                    'setting.form.dynamic_by_user.type_textarea' => Text::TYPE_TEXT_AREA,
                    'setting.form.dynamic_by_user.type_email'    => Text::TYPE_EMAIL_FIELD,
                    'setting.form.dynamic_by_user.type_number'   => Text::TYPE_NUMBER_FIELD,
                ]
            ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefault('data_class', Text::class);
    }
}

While i try to transmit the form, the request in the controller contains the form data as you can see it, in the following screenshot: enter image description here

My problem is now that i always get the following error (while handling the request for the form via ->handleRequest($request) on created form in controller):

Expected argument of type "?DoctrineCommonCollectionsCollection", "array" given at property path "textComponents".

I have such collection settings also in other classes, but without problems – I don’t know any further, can anyone please assist me or see the error?

(I am using Symfony version 5.2.9, if u need any further info just ask for it – I will give it to you as soon as possible)

Advertisement

Answer

Trying to add a constructor in your entity

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

Add addTextComponent and removeTextComponent methods intead of setTextComponents

public function addTextComponent(Text $textComponent): self
{
    $textComponent->setDynamicForm($this);
    $this->textComponents->add($textComponent);

    return $this;
}

public function removeTextComponent(Text $textComponent): self
{
    $this->textComponents->removeElement($textComponent);

    return $this;
}

Add 'by_reference' => false in the textComponents form params

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('textComponents', CollectionType::class, [
            'entry_type'    => TextType::class,
            'entry_options' => ['label' => false],
            'allow_add'     => true,
            'allow_delete'  => true,
            'label'         => ' ',
            'by_reference'  => false,
        ])
        ->add('submit', SubmitType::class, [
            'label' => 'form.basic.save'
        ]);
}
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement