Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedded form generates array instead of ArrayCollection

I'm trying to achieve some reusable translation in my bundle. These are the relevant parts of my code:

TranslatorKeys.php:

...
/**
 * @var \ArrayCollection
 * 
 * @ORM\OneToMany(targetEntity="Jumi\TranslatorBundle\Entity\TranslatorStrings", mappedBy="key")
 */
private $strings;
/**
 * @param Doctrine\Common\Collections\ArrayCollection $strings
 */
public function setStrings(ArrayCollection $strings) { // THIS IS LINE 84
    $this->strings = $strings;
}
...

TranslatorStrings.php:

/**
 * @var integer
 * 
 * @ORM\ManyToOne(targetEntity="Jumi\TranslatorBundle\Entity\TranslatorLanguages", fetch="LAZY")
 * @ORM\JoinColumns({
 *      @ORM\JoinColumn(name="language_id", referencedColumnName="id", nullable=false)
 * })
 */
private $language;
/**
 * @var string
 *
 * @ORM\Column(name="_value", type="string", nullable=true)
 */
private $value;
/**
 * @param string $value
 */
public function setValue($value) {
    $this->value = $value;
}

EmbeddableTranslatorKeyType.php:

note: translator_strings type is defined in TranslatorStringsType.php

...
public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('strings', 'collection', array(
        'type' => 'translator_strings',
        'options' => array(
            'form_type' => $options['form_type'],
            'required' => $options['required']
        ),
        'prototype' => true,
        'allow_add' => true,
        'allow_delete' => true
    ));
}

public function setDefaultOptions(OptionsResolverInterface $resolver) {
    $resolver->setDefaults(array(
        'data_class' => 'Jumi\TranslatorBundle\Entity\TranslatorKeys',
        'form_type' => 'text'
    ));
    $resolver->addAllowedValues(array(
        'form_type' => array(
            'text',
            'textarea'
        )
    ));
}
...

TranslatorStringsType.php

...
public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('value', $options['form_type'], array(
        'label' => false,
        'required' => $options['required']
    ));
    $builder->add('language', 'hidden');
}

public function setDefaultOptions(OptionsResolverInterface $resolver) {
    $resolver->setDefaults(array(
        'form_type' => 'text',
        'data_class' => 'Jumi\TranslatorBundle\Entity\TranslatorStrings'
    ));
    $resolver->addAllowedValues(array(
        'form_type' => array(
            'text',
            'textarea'
        )
    ));
}
...

And i'm trying to use embeddable_translator_key this way:

note: title is a many to one relation on TranslatorKeys

$builder->add('title', 'embeddable_translator_key', array(
            'label' => 'label_title',
            'required' => false
        ));

Now the problem is, that i got this exception on binding the request to the form:

Catchable Fatal Error: Argument 1 passed to
Jumi\TranslatorBundle\Entity\TranslatorKeys::setStrings() must be an instance of
Doctrine\Common\Collections\ArrayCollection, array given, called in
E:\prog\SymfonyExperiment\trunk\Symfony\vendor\symfony\symfony\src\Symfony\Component\PropertyAccess\PropertyAccessor.php on line 350 and defined in
E:\prog\SymfonyExperiment\trunk\Symfony\src\Jumi\TranslatorBundle\Entity\TranslatorKeys.php line 84

It's an easy workaround if i just remove the parameter type definition of ArrayCollection on line 84 in the TranslatorKeys Entity, and convert $strings to ArrayCollection if it's an array, but i rather search for a proper sollution.

If i didn't provided enough information feel free to ask for more!

Symfony experts are welcome!

like image 429
Jumi Avatar asked Mar 25 '26 06:03

Jumi


1 Answers

This issue probably relates to symfony/issues/4519.

You can work around this if you are using a version of symfony prior to the form refactoring by using:

public function setStrings($strings)
{ 
   $this->strings = is_array($strings) ? new ArrayCollection($strings) : $strings;
}

If you are using a newer version of symfony where this error does not occur you should better be type-checking for ArrayCollection but general Collection or leaving out the type-check completely:

/**
 * @param Doctrine\Common\Collections\Collection
 */ 
 public function setStrings(Collection $strings)
like image 98
Nicolai Fröhlich Avatar answered Mar 27 '26 18:03

Nicolai Fröhlich



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!