如何让Doctrine在Symfony2上的辅助函数中工作

Dom*_*oSL 4 php doctrine dependency-injection symfony

我需要在我的帮助器中使用doctrine,我试着在控制器中像我一样正常使用:

$giftRepository = $this->getDoctrine( )->getRepository( 'DonePunctisBundle:Gift' );
Run Code Online (Sandbox Code Playgroud)

但这给了我:

致命错误:调用未完成的方法DONE\PUNCTISBUNDLE\HELPER\UTILITYHELPER :: GETDOCTRINE()/VAR/WWW/VHOSTS/PUNCTIS.COM/HTTPDOCS/SRC/DONE/PUNCTISBUNDLE/HELPER/UTILITYHELPER.PH

我在这里失踪了什么?

编辑:

服务文件

services:
    templating.helper.utility:
        class: Done\PunctisBundle\Helper\UtilityHelper
        arguments: [@service_container]
        tags:
            - { name: templating.helper, alias: utility }
Run Code Online (Sandbox Code Playgroud)

第一行辅助文件

<?php
namespace Done\PunctisBundle\Helper;

use Symfony\Component\Templating\Helper\Helper;
use Symfony\Component\Templating\EngineInterface;



class UtilityHelper extends Helper {

    /*
     * Dependency injection
     */

    private $container;

    public function __construct( $container )
    {
        $this->container = $container;
    }
Run Code Online (Sandbox Code Playgroud)

Tho*_*ley 10

这里的问题是你的Helper类不是容器感知的; 也就是说,它不知道Symfony已经加载的所有服务(monolog,twig,...和doctrine).

你通过传递"教义"来解决这个问题.这称为依赖注入,是Symfony令人敬畏的核心内容之一.以下是它的工作原理:

首先,让你的Helper类为Doctrine服务提供一个生存的地方,并在Helper的构造函数中要求它:

class UtilityHelper
{
    private $doctrine;

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

    public function doSomething()
    {
        // Do something here
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,使用services.yml来定义Symfony应该如何构造Helper实例:

services:
    helper:
        class: Done\PunctisBundle\Helper\UtilityHelper
        arguments: [@doctrine]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,@doctrine占位符意味着"在此处插入Doctrine服务".

现在,在您的Controller中,或者在容器感知的任何其他内容中,您可以通过Helper类访问Doctrine,如下所示:

class SomeController()
{
    public function someAction()
    {
        $this->get("helper")->doctrine->getRepository(...);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

查看编辑后,您似乎将整个服务容器注入Helper类.这不是最好的做法 - 你应该只注射你需要的东西.但是,你仍然可以这样做:

services.yml

services:
    helper:
        class: Done\PunctisBundle\Helper\UtilityHelper
        arguments: [@service_container]
Run Code Online (Sandbox Code Playgroud)

UtilityHelper.php

class UtilityHelper
{
    private $container;

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

    public function doSomething()
    {
        // This won't work, because UtilityHelper doesn't have a getDoctrine() method:
        // $this->getDoctrine()->getRepository(...)

        // Instead, think about what you have access to...
        $container = $this->container;

        // Now, you need to get Doctrine

        // This won't work... getDoctrine() is a shortcut method, available only in a Controller
        // $container->getDoctrine()->getRepository(...)

        $container->get("doctrine")->getRepository(...)  
    }
}
Run Code Online (Sandbox Code Playgroud)

我在那里添加了一些评论,突出了一些常见的陷阱.希望这可以帮助.