web-dev-qa-db-fra.com

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

Cette question a commencé avec le fait que je ne comprenais pas pourquoi je ne pouvais pas passer de variables à une fonction d'assistance globale de symfony2 (service), mais grâce à des personnes plus lumineuses que moi, j'ai compris que mon erreur consistait à essayer d'utiliser le security_context à partir d'une classe ne ne pas l'avoir injecté alors ...

C'est le résultat final, le code qui fonctionne. Je n'ai trouvé aucun meilleur moyen 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 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
    }     
}

... défini comme un service (dans app/config/config.yml) comme celui-ci ...

#Registering my global helper functions            
services:
  biztv.helper.globalHelper:
    class: BizTV\CommonBundle\Helper\globalHelper
    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);
54
Matt Welander

Je suppose que la première erreur (propriété non définie) s'est produite avant l'ajout de la propriété et du constructeur. Ensuite, vous avez la deuxième erreur. Cette autre erreur signifie que votre constructeur s'attend à recevoir un objet Container mais qu'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épendance que vous souhaitiez obtenir le conteneur. Changez votre définition de service en ceci:

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

Le constructeur doit alors s'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;
    }
84
Carlos Granados

Une approche qui fonctionne toujours, même si elle n’est pas la meilleure pratique en matière d’exploitation

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

Une autre option consiste à étendre ContainerAware:

use Symfony\Component\DependencyInjection\ContainerAware;

class MyService extends ContainerAware
{
    ....
}

ce 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;
8
Jonathan

Ce n’est peut-être pas la meilleure solution, mais ce que je fais, c’est que je passe le conteneur à la classe afin de l’avoir à 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;
    }
    ...
}

Travaille chaque fois pour moi.

1
Strabek

Vous ne devez 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 au lieu. Voir, par exemple, la section "Eviter que votre code ne dépende 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
Tsounabe