3

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!

1
  • please review my answer and comment if anything unclear or it didn't work for you - otherwise please accept the answer :) Commented May 26, 2013 at 11:51

1 Answer 1

1

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)
Sign up to request clarification or add additional context in comments.

5 Comments

Doctrine\Common\Collections\Collection changes nothing. As the error says the parameter given is an array. I'm trying to find out why is it an array. I think it should be an ArrayCollection like in the example on symfony documentation. Of course that's a mutch simpler one.
@Jumi the arguments passed to this function can aswell be of type PersistentCollection in some cases. Collection is somehow like an Interface for those various collection-types because they all extend Collection. That's why i hinted you towards this - it had a similar issue in the past.
Well it's good to know. Unfortunately in my case it's not a Collection.
I'm already using a workaround like you suggested. As i'm using the newest stable version of symfony, it should not apply to me. Your answer is still helpful for those who experiencing similar problems on older versions. I'll post an issue on github.
It'd be awesome to see a neat "Correct Answer" mark on this instead of analizing if the author updated the FW version and why... :/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.