"无法反转属性路径的值"对于Symfony2,在Select2上形成ChoiceType字段

时间:2016-02-24 14:05:23

标签: php ajax forms symfony

长话短说,在Symfony 2.8中我有Movie个实体,actors字段,ArrayCollection实体ActorManyToMany )我希望该字段是ajax加载的Select2。 当我不使用Ajax时,表单是:

->add('actors', EntityType::class, array(
        'class' => Actor::class,
        'label' => "Actors of the work",
        'multiple' => true,
        'attr' => array(
          'class' => "select2-select",
         ),
       ))

可行

我试图在那里放一个空的选择字段:

->add('actors', ChoiceType::class, array(
    'mapped' => false,
    'multiple' => true,
    'attr'=>array(
        'class' => "select2-ajax",
        'data-entity'=>"actor"
    )
))

Select2 Ajax工作,DOM中的所有内容与前面的示例相同,但在表单提交中,我在分析器中遇到错误:This value is not valid.

Symfony\Component\Validator\ConstraintViolation
Object(Symfony\Component\Form\Form).children[actors] = [0 => 20, 1 => 21]
Caused by:
Symfony\Component\Form\Exception\TransformationFailedException
Unable to reverse value for property path "actors": Could not find all matching choices for the given values
Caused by:
Symfony\Component\Form\Exception\TransformationFailedException
Could not find all matching choices for the given values

有趣的是,收到的数据与EntityType时的数据相同:[0 => 20, 1 => 21]

我将字段标记为未映射,我甚至将字段名称更改为除电影实体的字段名称之外的其他名称。我尝试添加空choices,我尝试将其保留为EntityType,但使用自定义query_builder,返回空集合。现在我没有想法。

我该怎么做?

在雷蒙德的回答之后

编辑

我添加了DataTransformer:

use Doctrine\Common\Persistence\ObjectManager;
use CompanyName\Common\CommonBundle\Entity\Actor;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class ActorToNumberTransformer implements DataTransformerInterface
{
    private $manager;

    public function __construct(ObjectManager $objectManager)
    {
        $this->manager = $objectManager;
    }

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

        $actorIds = array();
        foreach($actors as $actor)
            $actorIds[] = $actor->getId();

        return $actorIds;
    }

    public function reverseTransform($actorIds)
    {
        if($actorIds === null)
            return array();

        foreach($actorIds as $actorId)
        {
            $actor = $this->manager->getRepository('CommonBundle:Actor')->find($actorId);
            if(null === $actor)
                throw new TransformationFailedException(sprintf('An actor with id "%s" does not exist!', $actorId));

            $actors[] = $actor;
        }

        return $actors;
    }
}

MovieType buildForm()

的末尾添加了它
$builder->get('actors')
    ->addModelTransformer(new ActorToNumberTransformer($this->manager));
$builder->get('actors')
    ->addViewTransformer(new ActorToNumberTransformer($this->manager));

并增加了服务:

common.form.type.work:
    class: CompanyName\Common\CommonBundle\Form\Type\MovieType
    arguments: ["@doctrine.orm.entity_manager"]
    tags:
        - { name: form.type }

没有任何改变。在表单提交上,reverseTransform()获取正确的数据,但是分析器显示相同的错误。这对我来说是一个很大的谜......

3 个答案:

答案 0 :(得分:1)

您需要添加DTO(数据转换器)来转换从表单接收的值并返回相应的对象。 由于您从Ajax调用了值,因此它不再将其识别为对象而是文本值。

示例:

  1. Symfony2 -Use of DTO
  2. Form with jQuery autocomplete

答案 1 :(得分:1)

正确的方法不是数据转换器,而是表单事件,请看这里: http://symfony.com/doc/current/form/dynamic_form_modification.html#form-events-submitted-data

在示例中,您拥有了field sport(一个实体,如Movie)和字段位置(另一个实体,如actors)。 诀窍是使用ajax以完全重新加载表单并使用 PRE_SET_DATAPOST_SUBMIT

我使用的是Symfony 3.x,但我认为它与2.8.x相同

答案 2 :(得分:0)

当您添加数据转换器时,似乎没有任何变化,听起来数据永远不会通过您的数据转换器。在调用新的数据转换器之前,转换可能会失败。尝试在代码中添加几行:

$builder->get('actors')->resetViewTransformers();
$builder->get('actors')->resetModelTransformers();
// and then add your own