【问题标题】:symfony2 injecting a dependence optimizationsymfony2 注入依赖优化
【发布时间】:2014-11-29 10:41:14
【问题描述】:

我有一个需要实体存储库的表单事件订阅者。 我想理想地注入这个存储库依赖项,而不必使用订阅者及其父对象的构造函数,因为这个订阅者需要以多种不同的形式。

所以基本上我有以下链:

控制器调用-> CustomManagerService 实例化-> 表单实例化-> EventSubscriber 需求-> EntityRepository

manager 已经是一项服务。将构造函数存储库参数从管理器通过表单传输到订阅者很痛苦,而且将每个表单设置为服务也很痛苦。

为什么我不能直接在订阅者中实例化存储库?我读过这是一种不好的做法。

编辑:这是我目前所拥有的:

在我的控制器中:

$unitRepository = $this->getDoctrine()->getRepository('UnitRepository');
$myManager = $this->get('my_manager')
$form = $myManager->createForm($unitRepository);

在我的管理器中:

public function createForm(UnitRepository $unitRepository){
return $this->formFactory->createForm(
new xxxType($unitRepository)
}

以我的形式:

use MyBundle/AddUnitFieldSubscriber;
protected $unitRepository;

public function __construct(UnitRepository $unitRepository)
{
$this->unitRepository = $unitRepository;
}

public function buildform()
{
$builder->addEventSubscriber(new AddUnitFieldSubscriber($this->unitRepository));
}

在我的订阅者中: 受保护的 $unitRepository;

public function __construct(UnitRepository $unitRepository)
{
$this->unitRepository = $unitRepository;
}
public function preSetData(FormEvent $event)
    {
$unitRepository = $this->unitRepository;
$unitRepository->doStuff()
}

我发现这非常冗长,有时我有一个调用子表单的表单,它是使用 eventSubscriber 的表单。如果我将表单设置为服务,有时也会出现错误,因为我在没有所需的第一个构造参数的情况下实例化它们。

在只知道订阅者需要访问存储库的情况下不重复所有这些操作的最短路径是什么?

非常感谢!

【问题讨论】:

  • 你能告诉我们你的服务定义吗?
  • 实例化存储库需要访问实体管理器(我假设您使用的是 Doctrine 2)。因此,直接在订阅者中实例化存储库将无济于事。如果表单需要注入额外的服务,那么您将表单设置为服务。一旦你做了一些,这很容易。您还可以将订阅者设为服务并将其注入到表单中。
  • @Cerad,那我需要将表单设为服务吗?如果我继续在我的 Manager 中实例化表单,比如 new xxxType() 没有参数,我感觉它会抛出一个错误,不是吗?

标签: symfony service constructor dependency-injection repository


【解决方案1】:

我真的不确定我是否理解所有内容甚至任何内容,但我会尝试做出回应。

我建议您定义一个服务SubscriberProvider,它将负责订阅者的实例化和订阅者中存储库的注入(通过订阅者的设置器)。您可以使用getretrievecreateprovide 或任何您喜欢的服务SubscriberProvider 的方法来检索订阅者的实例。然后,您可以将此提供程序注入另一个服务。

编辑

以下是与您的表单类型相关的服务定义:

services:
    your_own_bundle.form.type.unit:
        class: Your\OwnBundle\Form\Type\UnitType
        arguments:
            - "@doctrine"
        tags:
            - { name: form.type, alias: unit }

及其类:

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Your\OwnBundle\Event\AddUnitFieldSubscriber;

class UnitType extends AbstractType
{
    protected $unitRepository;

    public function __construct(ManagerRegistry $doctrine)
    {
        $this->unitRepository = $doctrine->getRepository('UnitRepository');
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventSubscriber(
            new AddUnitFieldSubscriber($this->unitRepository)
        );
    }

那么,你可以像这样使用这个类型:

$builder->add('available_unit', 'unit', array());

这样,您不必将存储库传递给您的经理。

【讨论】:

  • 我添加了完整的代码示例。在我已经拥有的众多解决方案之上,您的解决方案难道不是多了一个中介吗?
  • 设置代码以获取提供者中的存储库。将表单设置为服务。在表单服务中注入提供者。使用表单中的提供者获取AddUnitFieldSubscriber 的实例。这样你就不会有问题I also sometimes get errors cause I am instantiating them without the required first constructur parameter
  • 到目前为止,我的表单是从自定义管理器类中用新的 xxxType($this->unitRepository) 实例化的。如果我将它转换为服务,我需要在我的控制器中调用并将其作为参数传递,因为在我的管理器类中执行 new xxxType() 不会启动提供者构造函数参数('错误,预期提供者,给定 null' )。我对吗?然后它像以前一样复杂
  • 我为你写了一些代码。请注意,我直接在表单类型中完成工作,因此不需要提供者。
  • 如果我从控制器外部调用表单?我必须将表单作为自定义类的构造函数参数传递,或者在自定义类中实例化表单时找不到教义参数。我正在寻找一种方法让该订阅者不依赖于构造函数参数,因为它以多种形式使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
相关资源
最近更新 更多