58 votes

Comment injecter la @ demande dans un service?

Lorsque j'essaie d'injecter de l' @demande dans l'une de mes services, j'ai cette exception:

Scopewideninginjectionexception au: Portée de l'Élargissement de l'Injection détecté: La définition de "service de.de navigation" fait référence le service "demande" qui appartient à un champ d'application plus restreint. Généralement, il est plus sûr de soit déplacer "de service.de navigation" à la portée "demande" ou, alternativement, s'appuient sur le fournisseur de modèle en injectant le conteneur lui-même, et demandant le service "à la demande" chaque fois que cela est nécessaire. Dans de rares cas particuliers cependant, il pourrait ne pas être nécessaire, puis vous pouvez définir la référence à strict=false pour se débarrasser de cette erreur.

Quelle est la meilleure façon de procéder? Devrais-je essayer de définir cette strict=false et comment, ou devrais-je ne PAS injecter de la demande de service, mais plutôt de le passer au service par le biais de mon contrôleur à chaque fois que j'appel de fonctions dont j'ai besoin?

Autre possibilité serait d'injecter le noyau et à partir de là, mais dans mon service, je suis en utilisant seulement @routeur et @la demande, afin d'injecter de l'ensemble du noyau serait irrationnel.

Merci!

100voto

Blowski Points 7500

Dans Symfony 2.4, cela a changé. Maintenant, vous pouvez injecter le service 'request_stack'.

Par exemple:

 use Symfony\Component\HttpFoundation\RequestStack;

class MyService
{

    protected $request;

    public function setRequest(RequestStack $request_stack)
    {
        $this->request = $request_stack->getCurrentRequest();
    }

}
 

Dans votre config.yml:

 services:
    my.service:
        class: Acme\DemoBundle\MyService
        calls:
            - [setRequest, [@request_stack]]
 

La documentation complète est ici: http://symfony.com/blog/new-in-symfony-2-4-the-request-stack

31voto

Cerad Points 13840

Je pense qu'il peut y avoir eu un malentendu à propos de ce que la documentation officielle dit. Dans la plupart des cas, vous ne voulez injecter directement à la demande avec un scope="request" l'attribut de l'élément de service. De ce fait la Portée de l'Élargissement de s'en aller.

<service 
    id="zayso_core.openid.rpx" 
    class="Zayso\CoreBundle\Component\OpenidRpx" public="true" scope="request">

ou dans yml

zayso_core.openid.rpx: 
    class: Zayso\CoreBundle\Component\OpenidRpx
    public: true
    scope: request

C'est seulement dans certains cas particuliers tels que les extensions Twig où vous en avez besoin pour injecter le conteneur.

Et le noyau n'est même pas mentionné dans la page sur les étendues. L'injection du noyau est de loin pire (conceptuellement) que l'injection d'un conteneur.

Mise à JOUR: Pour S2.4 et versions ultérieures, utilisez @Blowski la réponse ci-dessous.

6voto

Anton Babenko Points 3359

Aujourd'hui, je suis passé par le même problème moi-même, voici donc mes 5 cents. Selon la documentation officielle , il n'est généralement pas nécessaire d'injecter request dans vos services. Dans votre classe de service vous pouvez passer kernel conteneur (injection, il n'est pas une grosse surcharge, à ce qu'il paraît), et ensuite accéder request comme ceci:

public function __construct(\AppKernel $kernel)
{
    $this->kernel = $kernel;
}

public function getRequest()
{
    if ($this->kernel->getContainer()->has('request')) {
        $request = $this->kernel->getContainer()->get('request');
    } else {
        $request = Request::createFromGlobals();
    }
    return $request;
}

Ce code est aussi bien fonctionner lorsque le service est accessible dans l'interface de ligne (par exemple, lors de tests unitaires).

5voto

yderay Points 81

Le meilleur moyen que j'ai trouvé pour faire en sorte qu'un service utilise le service de demande, ne repose pas sur le conteneur entier et ne soit toujours pas obligé d'avoir l'étendue de la demande, était de créer un service RequestInjector qui prend le conteneur. alors vous injectez cela dans le service qui veut utiliser l'objet de requête

 class RequestInjector{

    protected $container;

    public function __construct(Container $container){

         $this->container = $container;
   }

    public function getRequest(){

        return $this->container->get('request');
    }
}

class SomeService{

    protected $requestInjector;

    public function __construct(RequestInjector $requestInjector){

        $this->requestInjector = $requestInjector;

    }
}     
 

pour services.yml

 request_injector:
    class: RequestInjector
    public: false
    arguments: ['@service_container']

some_service:
    class: SomeService
    arguments: ['@request_injector']
 

4voto

simshaun Points 14463

Le moyen que j'ai trouvé, et je suis sûr que ce n'est probablement pas la meilleure façon (Peut-être même pas recommandé), est de définir la demande de service que synthétique.

Edit: en Effet, ce n'est pas recommandé, car il désactive le champ d'application des contrôles d'intégrité. Ce fil contient une bonne explication de pourquoi Symfony est de lancer cette exception: http://groups.google.com/group/symfony-devs/browse_thread/thread/a7207406c82ef07a/e2626c00f5cb9749

Dans votre services.xml:

<service id="request" synthetic="true" />

<service id="my_service" class="......">
    <argument type="service" id="request" />
</service>

Pour les docs, c'est mieux si vous placez votre service à la demande de la portée, ou tout simplement injecter le conteneur de services.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X