Comment accéder au conteneur de service dans la fonction d'assistance globale symfony2 (service)?

Cette question a commencé avec moi ne comprenant pas pourquoi je ne pouvais pas passer de variables à une fonction d'assistance globale symfony2 (service), mais grâce à des personnes plus brillantes que moi, j'ai réalisé que mon erreur consistait à essayer d'utiliser security_context à partir d'une classe qui ne l'a pas injectée...

C'est le résultat final, le code qui fonctionne. Je n'ai trouvé aucune meilleure façon de rendre cela utile à la communauté.

Voici comment vous pouvez obtenir l'utilisateur et d'autres données de security_context depuis une fonction globale ou une fonction d'assistance dans symfony2.

J'ai la classe et la fonction suivantes:

<?php
namespace BizTVCommonBundleHelper;

use SymfonyComponentDependencyInjectionContainerInterface 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
    }     
}

...défini comme un service (dans app/config/config.yml) comme ceci...

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

Maintenant, dans mon contrôleur, j'appelle cette fonction comme ceci...

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);
52
demandé sur Matt Welander 2012-08-21 17:40:26

5 réponses

Je suppose que la première erreur (propriété indéfinie) s'est produite avant d'ajouter la propriété et le constructeur. Ensuite, vous avez eu la deuxième erreur. Cette autre erreur signifie que votre constructeur s'attend à recevoir un objet conteneur mais il n'a rien reçu. En effet, lorsque vous avez défini votre service, vous n'avez pas indiqué au gestionnaire D'Injection de dépendances que vous vouliez obtenir le conteneur. Modifiez votre définition de service à ceci:

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

Le constructeur doit alors attendre un objet de type Symfony\Component\DependencyInjection\ContainerInterface;

use Symfony\Component\DependencyInjection\ContainerInterface as Container;

class globalHelper {    

    private $container;

    public function __construct(Container $container) {
        $this->container = $container;
    }
81
répondu Carlos Granados 2012-08-21 14:45:58

Une approche qui fonctionne toujours, bien que n'étant pas la meilleure pratique dans OO

global $kernel;
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');‏
20
répondu Guilherme Viebig 2014-04-01 21:40:57

Une autre option consiste à étendre ContainerAware:

use Symfony\Component\DependencyInjection\ContainerAware;

class MyService extends ContainerAware
{
    ....
}

Qui vous permet d'appeler setContainer dans la déclaration de service:

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

Vous pouvez ensuite référencer le conteneur dans votre service comme ceci:

$container = $this->container;
7
répondu Jonathan 2015-10-27 12:05:16

Peut-être que ce n'est pas le meilleur moyen, mais ce que je fais est de passer le conteneur à la classe, donc je l'ai chaque fois que j'en ai besoin.

$helpers = new Helpers();
or
$helpers = new Helpers($this->container);

/* My Class */
class Helpers
{
    private $container;

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

Fonctionne à chaque fois pour moi.

1
répondu Strabek 2016-04-08 10:22:15

, Vous ne devriez pas injecter le service_container dans vos services. Dans votre exemple, vous devriez plutôt injecter l'ancien security.context ou le plus récent security.token_storage à la place. Voir par exemple la section" éviter que votre Code ne devienne dépendant du conteneur " de http://symfony.com/doc/current/components/dependency_injection.html .

Ex:

<?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']

Votre contrôleur:

public function createAction($id) {

    $helper = $this->get('biztv.helper.globalHelper');
    $access = $helper->hasAccess($entity);
1
répondu Tsounabe 2016-10-27 14:59:21