banderos120
@banderos120
Играю на балалайке

Как использовать в формах choices с ArrayCollection, но не с Entity, а с обычным классом?

Здравствуйте.
Есть коллекция объектов Skills (в нем есть и геттеры и сеттеры), которые формируются из YML файла.
Есть мой тип поля (SET) у сущности User :
/**
     * @ORM\Column(type="skills", nullable=true)
     * @var ArrayCollection
     */
    private $skills;

Пробовал так :
//@UserType
            ->add('skills', 'collection', array(
                'type' => 'choice',
                'options' => array(
                    'choice_list' => new ObjectChoiceList(
                        $this->skillManager->getAllSkills()->toArray(),
                        'name',
                        array(),
                        null,
                        'alias'
                    ),
                    'multiple' => true
                )
            ));

Не записывает значения в поле skills в сущности, когда передаю массив (skills : ["skill_alias1", "skill_alias2"] ...). Просто пустая коллекция. Добавляю к полю "collection" еще параметр 'allow_add' => true, тогда коллекция набивается пустыми значениями (хотя должна работать с объектами класса Skill).
Когда же меняю просто на choice:
//@UserType
            ->add('skills', 'choice', array(
                'choice_list' => new ObjectChoiceList(
                    $this->skillManager->getAllSkills()->toArray(),
                    'name',
                    array(),
                    null,
                    'alias'
                ),
                'multiple' => true
            ));

, вместо collection, то выдает ошибку: Unable to transform value for property path "skills": Expected an array.

---------------------------------

Совсем ум за разум зашел. ArrayCollection - это доктриновский класс, по этому компонент формы не умеет с ним работать, а работает со стандартным array() . Я так понимаю, мне теперь нужно просто свой DataTransformer для этого поля написать и все ?
  • Вопрос задан
  • 849 просмотров
Решения вопроса 1
banderos120
@banderos120 Автор вопроса
Играю на балалайке
Короче быстро наваял сие чудо:
class ChoicesCollectionToArrayTransformer implements DataTransformerInterface
{

    private $choiceList;

    public function __construct(ChoiceListInterface $choiceList)
    {
        $this->choiceList = $choiceList;
    }

    public function transform($collection)
    {
        if (null === $collection) {
            return array();
        }

        if (is_array($collection)) {
            return $collection;
        }

        if (!$collection instanceof Collection) {
            throw new TransformationFailedException('Expected a Doctrine\Common\Collections\Collection object.');
        }

        return $this->choiceList->getValuesForChoices($collection->toArray());
    }

    public function reverseTransform($array)
    {
        if ('' === $array || null === $array) {
            $array = array();
        } else {
            $array = (array) $array;
        }

        $choices = $this->choiceList->getChoicesForValues($array);

        if (count($choices) !== count($array)) {
            throw new TransformationFailedException('Could not find all matching choices for the given values');
        }

        return new ArrayCollection($choices);
    }
}


И использовал в UserType:
$skillsChoiceList = new ObjectChoiceList(
            $this->skillManager->getAllSkills()->toArray(),
            'name',
            array(),
            null,
            'alias'
        );

$builder ->add('skills', 'choice', array(
                'choice_list' => $skillsChoiceList,
                'multiple' => true
            ));

$builder->get('skills')->resetViewTransformers()->addViewTransformer(new ChoicesCollectionToArrayTransformer($skillsChoiceList));


Работает.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
prototype_denis
@prototype_denis
Symfony
@ORM\Column(type="skills", nullable=true)

(type="skills", nullable=true)

type="skills"

skills

О_о
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы