Symfony 2:依赖注入和traits

16
我想找到一种方法,使用Symfony 2的Dependency Injection组件和新的PHP 5.4trait。我的项目有解耦的View类,它们都有自己特定的构造函数。每个View可以使用零个或多个视图帮助器,这些视图帮助器被定义为traits。
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);
    }
}
class UserEditView extends AbstractView
{
    use TranslatorHelper;

    public function __construct(User $user, UserEditForm $form)
    {
        // ...
    }
}

我想在我的控制器中添加一个方法renderView(),这个方法会在渲染视图之前根据View类使用的所有traits执行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();
    }
}
任何想法如何使用DependencyInjection组件完成这个功能?
主要问题显然是视图不会由DI容器创建,但可以在应用程序流的任何位置创建。只有在呈现之前才需要注入依赖项。
最后注意:我不局限于Symfony组件。任何其他DI容器的线索也将不胜感激。

您可以尝试使用AOP进行DI:https://github.com/schmittjoh/JMSAopBundle/blob/master/Resources/doc/index.rst,通过属性和参数的注释自动注入服务。 - lisachenko
问题在于我想保持视图助手(例如TranslatorHelper)的通用性,因此理想情况下它们不应该包含容器中依赖项的特定于项目的ID。 - BenMorel
2个回答

21

6

我认为特质不应该用于这种方式的依赖注入。 在类似的情况下,我会在实现特质的视图类中使用构造函数注入(即使使用setter也可以,但如果可能的话,构造函数更好)。通过直接注入所需服务。

如果您考虑到由类实现的特质在应用程序执行之前静态定义,因此您不需要检查特质以执行动态注入。运行之前,您将知道需要哪些服务,只需将特质视为带有某些具体方法的接口即可。


我理解你的意思,但我的担忧是我想让View构造函数清晰明了,不涉及任何Helper特定的依赖项(我希望控制器明确使用View构造函数仅传递视图本身所需的变量,而无需担心Helpers)。此外,我可能会有数百个View类,所有这些类都使用相同的 ~3个视图助手。因此,我更喜欢能够基于Trait名称进行注入。例如,我想在我的配置中定义,所有使用“TranslatorHelper” trait 的类都将使用由“translator”容器键指向的Translator。 - BenMorel
3
在这种情况下,你可以使用依赖注入(DI)标记:定义一个标记和一个编译器传递,用于为每个帮助程序特性注册正确的setter依赖项。最近在Symfony文档中发布了一些有关高级DIC使用(如编译器传递和标记)的文档。它不是基于特性自动注入的(我认为唯一的方法是使用相当慢的反射),但它非常整洁干净。 - Aldo Stracquadanio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接