我做到了。使用数据转换器,但我们需要为集合制作转换器,而不是为集合中的字段。
所以它看起来像那样(有效!)。
我的 PostType.php 表单需要有实体管理器(如内部文档,关于数据转换器)和用于收集的数据转换器,所以我添加了:
# PostType.php form
namespace BlogBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use BlogBundle\Form\DataTransformer\TagToIdTransformer;
use Doctrine\Common\Persistence\ObjectManager;
class PostType extends AbstractType
{
private $manager;
public function __construct(ObjectManager $manager)
{
// needed for transformer :(
// and we need to register service inside app config for this. Details below
$this->manager = $manager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tag', CollectionType::class, array(
'entry_type' => TagType::class,
'by_reference' => false,
'allow_add' => true,
))
->add('save', SubmitType::class, array('label' => 'Save'));
$builder->get('tag')
->addModelTransformer(new TagToIdTransformer($this->manager));
}
}
构造函数会抛出异常,我们需要将 ObjectManager 传递给它。要做到这一点,请修改捆绑包中的配置文件:
# src/BlogBundle/Resources/config/services.yml
services:
blog.form.type.tag:
class: BlogBundle\Form\PostType
arguments: ["@doctrine.orm.entity_manager"]
tags:
- { name: form.type }
现在让我们为一个集合制作转换器!我之前做错了,因为我试图为一个领域制作像内部文档一样的东西。对于集合,我们需要转换整个标签数组(它的 manyToMany 集合):
<?php
namespace BlogBundle\Form\DataTransformer;
use BlogBundle\Entity\Tag;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
class TagToIdTransformer implements DataTransformerInterface
{
private $manager;
public function __construct(ObjectManager $manager)
{
$this->manager = $manager;
}
/**
* Transforms array of objects (Tag) to an array of string (number).
*
* @param array|null $tags
* @return string
*/
public function transform($tags)
{
$result = array();
if (null === $tags) {
return null;
}
foreach ($tags as $tag)
{
$result[] = $tag->getTagId();
}
return $result;
}
/**
* Transforms an array of strings (numbers) to an array of objects (Tag).
*
* @param string $tagsId
* @return Tag|null
* @throws TransformationFailedException if object (Tag) is not found.
*/
public function reverseTransform($tagsId)
{
// no issue number? It's optional, so that's ok
if (!$tagsId) {
return;
}
$result = array();
$repository = $this->manager
->getRepository('BlogBundle:Tag');
foreach ($tagsId as $tagId) {
$tag = $repository->find($tagId);
if (null === $tag) {
// causes a validation error
// this message is not shown to the user
// see the invalid_message option
throw new TransformationFailedException(sprintf(
'An tag with id "%s" does not exist!',
$tagId
));
}
$result[] = $tag;
}
return $result;
}
}
现在一切正常。我可以使用仅填充标签 ID 的自动完成功能轻松保存我的实体