Symfony 2:依赖注入和特征

Ben*_*min 12 php dependency-injection symfony

我试图找到一种方法来使用Symfony 2 依赖注入组件与新的PHP 5.4 特征.

长话短说(实际上不是那么短),我的项目已经解耦了View类,它们都有自己的特定构造函数.每个View都可以使用零个或多个视图助手,这些助手被定义为特征:

trait TranslatorHelper
{
    /**
     * @var Translator
     */
    protected $translator;

    /**
     * @param Translator $translator
     */
    protected function setTranslator(Translator $translator)
    {
        $this->translator = $translator;
    }

    /**
     * @param string $text
     * @return string
     */
    public function translate($text)
    {
        return $this->translator->translate($text);
    }
}
Run Code Online (Sandbox Code Playgroud)

-

class UserEditView extends AbstractView
{
    use TranslatorHelper;

    public function __construct(User $user, UserEditForm $form)
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望在我的控制器中有一个方法renderView(),它在渲染视图之前根据View类使用的所有特征执行setter注入:

class Controller
{
    public function renderView(View $view)
    {
        // Check what traits are used by $view, and inject their dependencies
        // {...}


        // Then render the View
        return $view->render();
    }
}
Run Code Online (Sandbox Code Playgroud)

有关如何使用DependencyInjection组件执行此操作的任何想法?

主要问题显然是视图不会由DI容器创建,但可以在应用程序流中的任何位置创建.只有在它们呈现之前,才需要注入依赖项.

最后一点:我没有与Symfony组件绑定.另一个DI容器上的任何导线也将受到赞赏.

小智 11

Symfony 3.3引入了自动服务的概念.
您所要做的就是在特征中创建一个setter函数并添加@required注释.

private $entityManager;

/**
 * @required
 * @param EntityManagerInterface $entityManager
 */
public function setEntityManager(EntityManagerInterface $entityManager)
{
    $this->entityManager = $entityManager;
}
Run Code Online (Sandbox Code Playgroud)

参考:https://symfony.com/doc/current/service_container/autowiring.html#autowiring-other-methods-eg-setters


Ald*_*nio 6

我认为这种特性并不意味着以这种方式用于做DI.我在类似场景中会做的是在视图类中使用构造函数注入(甚至setter会很好,甚至很难构造函数更好),它实现了直接注入所需服务的特性.

如果您考虑在应用程序执行之前静态定义类实现的特征,那么您实际上不需要检查特征来执行动态注入.在运行之前,您将了解所需的服务,只需将其视为具有某种具体方法的接口即可.

  • 在这种情况下,你可以做的是使用DI标记:定义一个标记和一个编译器传递,寄存器为每个帮助程序特征做出正确的setter依赖.最近在Symfony文档中发布了一些关于高级DIC使用的文档(例如编译器通行证和标签).它不是基于特征自动注入(我认为这样做的唯一方法就是使用非常慢的反射),但它非常整洁干净. (3认同)