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);
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;
}
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');
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;
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.
, 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);