Symfony2自定义表单类型带数据变换器 - 服务注入

时间:2016-08-31 10:27:02

标签: forms symfony doctrine symfony-2.8

我正在实现一个带有数据转换器的自定义表单类型,以根据http://symfony.com/doc/2.8/form/data_transformers.html

实现多对多关系
class ClientType extends AbstractType
{
    private $manager;

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

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('shortname')
            ->add('shortinfo')
            ->add('web')                
            ->add('user', CollectionType::class, array(
                'entry_type'     => IntegerType::class,
                'allow_add'      => true,
                'allow_delete'   => true
            ));

        $builder->get('user')->addModelTransformer(new UserToPrimaryKeyTransformer($this->manager));
    }
}

子类型UserType是:

class UserType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('loginname')
            ->add('firstname')
            ->add('lastname')
            /* ... */
            ->add('email')
            ->add('id')
        ;
    }
}

变换器类几乎是从文档中复制粘贴的:

class UserToPrimaryKeyTransformer implements DataTransformerInterface
{

    private $manager;

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

    /**
     * Transform entity to pkid
     *
     * @param User
     * @return integer
     */
    public function transform($user)
    {
        if(null === $user) {
            return -1;
        }

        return $user->getId();
    }

    /**
     * @param integer $pkid
     */
    public function reverseTransform($pkid)
    {
        if (!$pkid) {
            return;
        }

        $user = $this->manager
            ->getRepository('AcmeBundle:User')
            // query for the user with this id
            ->find($pkid)
        ;

        if (null === $user) {
            /* ... */
        }

        return $user;
    }

}

对于上下文来说太多了。然而,问题似乎在于服务定义,正是注入Doctrine Entity Manager:

acme.form.type.client:
    class: AcmeBundle\Form\ClientType
    arguments: [ @doctrine.orm.entity_manager ]
    tags:
       - { name: form.type }

现在,当我发布此表单时,我得到: Type error: Argument 1 passed to AcmeBundle\Form\ClientType::__construct() must implement interface Doctrine\Common\Persistence\ObjectManager, none given

有关正在发生的事情的任何想法或指示? @doctrine.orm.entity_manager变量是否必须在某处实例化?

我在Symfony 2.8,顺便说一句

2 个答案:

答案 0 :(得分:0)

发现了这个问题。我忘记了我是手动实例化表单以满足API要求(它是我正在开发的REST服务):

// create a form with an empty name in order to avoid needing a JSON ROOT element
$form = $this->get('form.factory')->createNamed('', new \AcmeBundle\Form\ClientType(), $client);
将此更改为

$form = $this->get('form.factory')->createNamed('', new \AcmeBundle\Form\ClientType($em), $client);

它有效。

谢谢大家!

答案 1 :(得分:-1)

您的表单类型需要ObjectManager并且您正在注入EntityManager。我建议将构造函数参数更改为EntityManager,它将正常工作