如何访问symfony2全局助手函数(service)中的服务容器


How to access service container in symfony2 global helper function (service)?

这个问题一开始我不明白为什么我不能将变量传递给symfony2全局帮助函数(服务),但多亏了比我聪明的人,我意识到我的错误是试图在一个没有注入安全上下文的类中使用它,所以…

这是最终的结果,是有效的代码。我找不到更好的方法使这对社区有帮助。

这就是如何从symfony2中的全局函数或辅助函数中的security_context获取用户和其他数据。

我有以下类和函数:

<?php
namespace BizTV'CommonBundle'Helper;
use Symfony'Component'DependencyInjection'ContainerInterface as Container;
class globalHelper {    
private $container;
public function __construct(Container $container) {
    $this->container = $container;
}   
    //This is a helper function that checks the permission on a single container
    public function hasAccess($container)
    {
        $user = $this->container->get('security.context')->getToken()->getUser();
        //do my stuff
    }     
}

定义为这样的服务(在app/config/config.yml中)。。。

#Registering my global helper functions            
services:
  biztv.helper.globalHelper:
    class: BizTV'CommonBundle'Helper'globalHelper
    arguments: ['@service_container']

现在,在我的控制器中,我这样调用这个函数。。。

public function createAction($id) {
    //do some stuff, transform $id into $entity of my type...
    //Check if that container is within the company, and if user has access to it.
    $helper = $this->get('biztv.helper.globalHelper');
    $access = $helper->hasAccess($entity);

我假设第一个错误(未定义的属性)发生在添加属性和构造函数之前。然后你又犯了第二个错误。另一个错误意味着您的构造函数希望接收一个Container对象,但它什么也没收到。这是因为在定义服务时,您没有告诉依赖注入管理器您想要获取容器。将您的服务定义更改为:

services:
  biztv.helper.globalHelper:
    class: BizTV'CommonBundle'Helper'globalHelper
    arguments: ['@service_container']

构造函数应该期望一个类型为Symfony''Component''DependencyInjection''ContainerInterface;

use Symfony'Component'DependencyInjection'ContainerInterface as Container;
class globalHelper {    
    private $container;
    public function __construct(Container $container) {
        $this->container = $container;
    }

一种始终有效的方法,尽管它不是OO 中的最佳实践

global $kernel;
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');‏

另一个选项是扩展ContainerWare:

use Symfony'Component'DependencyInjection'ContainerAware;
class MyService extends ContainerAware
{
    ....
}

它允许您在服务声明中调用setContainer

foo.my_service:
    class: Foo'Bundle'Bar'Service'MyService
    calls:
        - [setContainer, [@service_container]]

然后,您可以这样引用服务中的容器:

$container = $this->container;

也许这不是最好的方法,但我所做的是将容器传递给类,以便每次需要时都有它。

$helpers = new Helpers();
or
$helpers = new Helpers($this->container);
/* My Class */
class Helpers
{
    private $container;
    public function __construct($container = null) {
        $this->container = $container;
    }
    ...
}

每次对我都有效。

您不应该在服务中注入service_container。在您的示例中,您应该注入旧的security.context或更新的security.token_storage。例如,请参阅http://symfony.com/doc/current/components/dependency_injection.html.

例如:

<?php
namespace BizTV'CommonBundle'Helper;
use Symfony'Component'Security'Core'Authentication'Token'Storage'TokenStorage;
class globalHelper {    
    private $securityTokenStorage;
    public function __construct(TokenStorage $securityTokenStorage) {
        $this->securityTokenStorage= $securityTokenStorage;
    }   

    public function hasAccess($container)
    {
        $user = $this->securityTokenStorage->getToken()->getUser();
        //do my stuff
    }     
}

app/config/config.yml:

services:
  biztv.helper.globalHelper:
    class: BizTV'CommonBundle'Helper'globalHelper
    arguments: ['@security.token_storage']

您的控制器:

public function createAction($id) {
    $helper = $this->get('biztv.helper.globalHelper');
    $access = $helper->hasAccess($entity);