我在使用 tagsinput 的表单上使用标签:
此插件以单个文本字段结束,其中包含以逗号分隔的标签(例如:tag1,tag2,...)
这些标签目前在非映射表单字段上进行管理:
$builder
// ...
->add('tags', 'text', array(
'mapped' => false,
'required' => false,
))
;
最后,它们存储在 ArrayCollection 中,如 this is a bad practice to store multiple values in a database field :
/**
* @var ArrayCollection[FiddleTag]
*
* @ORM\OneToMany(targetEntity="FiddleTag", mappedBy="fiddle", cascade={"all"}, orphanRemoval=true)
*/
protected $tags;
为了将我的表单映射到我的实体,我可以在我的 Controller 中编写一些代码,如下所示:
$data->clearTags();
foreach (explode(',', $form->get('tags')->getData()) as $tag)
{
$fiddleTag = new FiddleTag();
$fiddleTag->setTag($tag);
$data->addTag($fiddleTag);
}
但乍一看这是错误的方式。
我想知道将我的实体映射到我的表单,以及将我的表单映射到我的实体的最佳做法是什么。
最佳答案
这很棘手,因为您不只是嵌入一组标签表单,也就是说,所有单独的文本字段。我想你可以通过一些技巧来做到这一点,但是使用数据转换器呢?您可以将逗号分隔的标签列表转换为 ArrayCollection 并将其传回表单,另一方面,获取集合并将标签作为逗号分隔的字符串返回。
数据转换器
FiddleTagsTransformer.php
<?php
namespace Fuz\AppBundle\Transformer;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Form\DataTransformerInterface;
use Fuz\AppBundle\Entity\FiddleTag;
class FiddleTagTransformer implements DataTransformerInterface
{
public function transform($tagCollection)
{
$tags = array();
foreach ($tagCollection as $fiddleTag)
{
$tags[] = $fiddleTag->getTag();
}
return implode(',', $tags);
}
public function reverseTransform($tags)
{
$tagCollection = new ArrayCollection();
foreach (explode(',', $tags) as $tag)
{
$fiddleTag = new FiddleTag();
$fiddleTag->setTag($tag);
$tagCollection->add($fiddleTag);
}
return $tagCollection;
}
}
注意:您不能将 ArrayCollection 类型指定给 public function transform($tagCollection)
,因为您的实现应该与接口(interface)匹配。
表单类型
第二步是替换你的表单字段声明,这样它就可以透明地使用数据转换器,你甚至不需要在你的 Controller 中做任何事情:
FiddleType.php
$builder
// ...
->add(
$builder
->create('tags', 'text', array(
'required' => false,
))
->addModelTransformer(new FiddleTagTransformer())
)
;
验证
您可以使用 @Assert\Count限制允许的标签数量,@Assert\Valid如果您的 FiddleTag 实体本身有一些验证约束。
Fiddle.php
/**
* @var ArrayCollection[FiddleTag]
*
* @ORM\OneToMany(targetEntity="FiddleTag", mappedBy="fiddle", cascade={"all"}, orphanRemoval=true)
* @Assert\Count(max = 5, maxMessage = "You can't set more than 5 tags.")
* @Assert\Valid()
*/
protected $tags;
进一步阅读
请参阅有关数据转换器的 Symfony2 文档:http://symfony.com/doc/current/cookbook/form/data_transformers.html
查看这些帖子以获得其他一些想法:
Parsing comma separated string into multiple database entries (eg. Tags)
关于php - 将表单的文本字段映射到实体的 ArrayCollection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27681395/