Symfony 2:依赖注入和特征


Symfony 2: dependency injection and traits

我正试图找到一种方法来使用具有新的PHP 5.4特性的Symfony 2依赖注入组件。

长话短说(实际上不那么简短),我的项目已经解耦了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);
    }
}

-

class UserEditView extends AbstractView
{
    use TranslatorHelper;
    public function __construct(User $user, UserEditForm $form)
    {
        // ...
    }
}

我希望在我的控制器renderView()中有一个方法,它在渲染View:之前,根据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();
    }
}

关于如何使用DependencyInjection组件,有什么想法吗?

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

最后一点:我没有被Symfony组件束缚住。另一个DI容器上的任何线索也将不胜感激。

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

private $entityManager;
/**
 * @required
 * @param EntityManagerInterface $entityManager
 */
public function setEntityManager(EntityManagerInterface $entityManager)
{
    $this->entityManager = $entityManager;
}

参考:https://symfony.com/doc/current/service_container/autowiring.html#autowiring-其他方法-e-g-setters

我认为特征不应该用来以这种方式进行DI。在类似的场景中,我会在实现特性的视图类中使用构造函数注入(或者甚至setter也可以,如果可能的话,即使是严格的构造函数也更好)来直接注入所需的服务。

如果您认为类实现的特性是在应用程序执行之前静态定义的,那么您实际上不需要检查特性来执行动态注入。在运行之前,您将知道需要什么服务,只需将它们视为具有某种具体方法的接口即可。