长话短说,在Symfony 2.8中我有Movie
个实体,actors
字段,ArrayCollection
实体Actor
(ManyToMany
)我希望该字段是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()
获取正确的数据,但是分析器显示相同的错误。这对我来说是一个很大的谜......
答案 0 :(得分:1)
您需要添加DTO(数据转换器)来转换从表单接收的值并返回相应的对象。 由于您从Ajax调用了值,因此它不再将其识别为对象而是文本值。
示例:
答案 1 :(得分:1)
正确的方法不是数据转换器,而是表单事件,请看这里: http://symfony.com/doc/current/form/dynamic_form_modification.html#form-events-submitted-data
在示例中,您拥有了field sport(一个实体,如Movie
)和字段位置(另一个实体,如actors
)。
诀窍是使用ajax以完全重新加载表单并使用
PRE_SET_DATA
和POST_SUBMIT
。
我使用的是Symfony 3.x,但我认为它与2.8.x相同
答案 2 :(得分:0)
当您添加数据转换器时,似乎没有任何变化,听起来数据永远不会通过您的数据转换器。在调用新的数据转换器之前,转换可能会失败。尝试在代码中添加几行:
$builder->get('actors')->resetViewTransformers();
$builder->get('actors')->resetModelTransformers();
// and then add your own