web-dev-qa-db-fra.com

Comment accéder aux paramètres d'une application depuis un service?

Depuis mes contrôleurs, j’accède aux paramètres de l’application (ceux de /app/config) Avec

$this->container->getParameter('my_param')

Mais je ne sais pas comment y accéder depuis un service (j'imagine que ma classe de service n'est pas censée s'étendre Symfony\Bundle\FrameworkBundle\Controller\Controller).

Devrais-je mapper les paramètres nécessaires dans mon enregistrement de service comme ceci:

#src/Me/MyBundle/Service/my_service/service.yml
parameters:
    my_param1: %my_param1%
    my_param2: %my_param2%
    my_param3: %my_param3%

ou quelque chose de similaire? Comment dois-je accéder aux paramètres de mon application depuis un service?


Cette question semble être la même chose mais la mienne y répond (paramètres d'un contrôleur), je parle d'accès depuis un service.

68
Pierre de LESPINAY

Vous pouvez transmettre des paramètres à votre service de la même manière que vous injectez d'autres services, en les spécifiant dans votre définition de service. Par exemple, en YAML:

services:
    my_service:
        class:  My\Bundle\Service\MyService
        arguments: [%my_param1%, %my_param2%]

où le %my_param1% etc correspond à un paramètre nommé my_param1. Votre constructeur de classe de service pourrait alors être:

public function __construct($myParam1, $myParam2)
{
    // ...
}
113
richsage

La voie propre 2018

Depuis 2017 et Symfony 3.4 , il existe un moyen beaucoup plus propre - facile à installer et à utiliser.

Au lieu d'utiliser l'anti-modèle de conteneur et de localisateur de service/paramètre, vous pouvez transmettre des paramètres à class via son constructeur . Ne vous inquiétez pas, ce n'est pas un travail qui demande du temps, mais plutôt installer une fois et oublier.

Comment le configurer en 2 étapes?

1. config.yml

# config.yml

# config.yml
parameters:
    api_pass: 'secret_password'
    api_user: 'my_name'

services:
    _defaults:
        autowire: true
        bind:
            $apiPass: '%api_pass%'
            $apiUser: '%api_user%'

    App\:
        resource: ..

2. Tout Controller

<?php declare(strict_types=1);

final class ApiController extends SymfonyController
{
    /**
     * @var string 
     */
    private $apiPass;

    /**
     * @var string
     */
    private $apiUser;

    public function __construct(string $apiPass, string $apiUser)
    {
        $this->apiPass = $apiPass;
        $this->apiUser = $apiUser;
    }

    public function registerAction(): void
    {
        var_dump($this->apiPass); // "secret_password"
        var_dump($this->apiUser); // "my_name"
    }
}

Mise à niveau instantanée prête!

Si vous utilisez une approche plus ancienne, vous pouvez l’automatiser avec Rector .

Lire la suite

Cette approche s'appelle l'injection du constructeur sur le localisateur de services .

Pour en savoir plus à ce sujet, consultez mon article Comment obtenir les paramètres dans le contrôleur Symfony de manière propre .

(Il a été testé et je le garde à jour pour la nouvelle version majeure de Symfony (5, 6 ...)).

20
Tomáš Votruba

Au lieu de mapper les paramètres nécessaires un par un, pourquoi ne pas autoriser votre service à accéder directement au conteneur? Pour ce faire, vous n'avez pas besoin de mettre à jour votre mappage si de nouveaux paramètres sont ajoutés (relatifs à votre service).

Faire cela:

Apportez les modifications suivantes à votre classe de service

use Symfony\Component\DependencyInjection\ContainerInterface; // <- Add this

class MyServiceClass
{
    private $container; // <- Add this
    public function __construct(ContainerInterface $container) // <- Add this
    {
        $this->container = $container;
    }
    public function doSomething()
    {
        $this->container->getParameter('param_name_1'); // <- Access your param
    }
}

Ajoutez @service_container comme "arguments" dans votre service.yml

services:
  my_service_id:
    class: ...\MyServiceClass
    arguments: ["@service_container"]  // <- Add this
18
Ham L.

Pour résoudre certains des problèmes mentionnés, je définis un paramètre de tableau, puis je l’injecte. L'ajout ultérieur d'un nouveau paramètre nécessite simplement l'ajout d'un tableau de paramètres sans aucune modification des arguments ou de la construction service_container.

Donc, prolongeant la réponse @richsage:

paramètres.yml

parameters:
    array_param_name:
        param_name_1:   "value"
        param_name_2:   "value"

services.yml

services:
    my_service:
        class:  My\Bundle\Service\MyService
        arguments: [%array_param_name%]

Puis accès en classe

public function __construct($params)
{
    $this->param1 = array_key_exists('param_name_1',$params)
        ? $params['param_name_1'] : null;
    // ...
}
6
Dave

Il y a un nouveau moyen très propre de le réaliser depuis symfony 4.1

<?php
// src/Service/MessageGeneratorService.php

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class MessageGeneratorService
{
 private $params;
 public function __construct(ParameterBagInterface $params)
 {
      $this->params = $params;
 }
 public function someMethod()
 {
     $parameterValue = $this->params->get('parameter_name');
...
 }
}

source: https://symfony.com/blog/new-in-symfony-4-1-getting-container-parameters-as-a-service .

3
Ousmane

Avec Symfony 4.1 la solution est assez simple.

Voici un extrait du message original:

// src/Service/MessageGenerator.php
// ...

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class MessageGenerator
{
    private $params;

    public function __construct(ParameterBagInterface $params)
    {
        $this->params = $params;
    }

    public function someMethod()
    {
        $parameterValue = $this->params->get('parameter_name');
        // ...
    }
}

Lien vers le message d'origine: https://symfony.com/blog/new-in-symfony-4-1-getting-container-parameters-as-a-service

2
Carol-Theodor Pelu

Dans symfony 4, nous pouvons accéder aux paramètres au moyen d’une injection de dépendance:

Prestations de service:

   use Symfony\Component\DependencyInjection\ContainerInterface as Container;

   MyServices {

         protected $container;
         protected $path;

         public function __construct(Container $container)
         {
             $this->container = $container;
             $this->path = $this->container->getParameter('upload_directory');
         }
    }

parameters.yml:

parameters:
     upload_directory: '%kernel.project_dir%/public/uploads'
0
shades3002