【问题标题】:Symfony2 Custom Form Type w/Data Transformer - Service Injection带数据转换器的 Symfony2 自定义表单类型 - 服务注入
【发布时间】:2016-08-31 10:27:02
【问题描述】:

我正在使用数据转换器实现自定义表单类型,以根据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')
        ;
    }
}

transformer 类几乎是从文档中复制粘贴的:

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 上,顺便说一句

【问题讨论】:

  • 您的服务定义有误吗?因为你说的是​​AcmeBundle\Form\ClientType 而不是AcmeBundle\Form\ CrmClientType
  • 不,对不起...忘记简化那个...在这两种情况下都应该是AcmeBundle\Form\ClientType

标签: forms symfony doctrine symfony-2.8


【解决方案1】:

发现了问题。我忘记了我手动实例化表单是为了满足 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);

成功了。

谢谢大家!

【讨论】:

  • 为什么要手动处理依赖关系?您的表单类型已注册,因此您可以从容器中获取它
  • 这是非常正确的。如上面评论中所述,有必要创建一个名称为空的表单,以删除原本需要的 JSON 根元素。如果您有更好的解决方案,我会很高兴!
  • 这样的东西怎么样:$this->createForm($formType, ['form_alias/name' => $client]);
  • 请注意,将实际表单类型实例传递给表单工厂在 S2 中会被贬值,而在 S3 中会消失。因此,如果您计划升级,那么您将需要进行一些认真的重构。如果您已经在 S2.8 上,则只需传递 ClientType 的类名而不是实例。奇怪的是,随后将使用服务定义并为您注入实体管理器。
  • 还有一个建议,将您的转换器定义为服务并将其注入 ClientType。这样一来,ClientType 就不需要和实体管理器鬼混了。
【解决方案2】:

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

【讨论】:

  • 不,这不是真的,首先,错误表明他传递的是 null,其次,EntityManager 实现了 ObjectManager(通过 EntityManagerInterface
  • 这是正确的@DonCallisto,根据docs(有点难找到)通过EntityManagerInterface
猜你喜欢
  • 1970-01-01
  • 2010-10-11
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-17
  • 1970-01-01
相关资源
最近更新 更多