Comment lire des paramètres.yml dans un contrôleur dans symfony2?


146

J'ai mis quelques variables personnalisées dans mon app / config / parameters.yml.

parameters:
    api_pass: apipass
    api_user: apiuser

Je dois y accéder depuis ma manette et j'ai essayé de les récupérer avec

$this->get('api_user');

à partir de mon fichier de contrôleur. Quand j'essaye ceci, j'obtiens ce message d'erreur:

You have requested a non-existent service "api_user".

Quelle est la bonne façon de procéder?

Réponses:


296

Dans Symfony 2.6 et les versions antérieures , pour obtenir un paramètre dans un contrôleur, vous devez d'abord obtenir le conteneur, puis le paramètre nécessaire.

$this->container->getParameter('api_user');

Ce chapitre de documentation l' explique.

Alors que la $this->get()méthode dans un contrôleur chargera un service ( doc )

Dans Symfony 2.7 et les versions plus récentes , pour obtenir un paramètre dans un contrôleur, vous pouvez utiliser ce qui suit:

$this->getParameter('api_user');

3
Notez que la getméthode du contrôleur utilise également le conteneur, mais elle ne peut obtenir des services qu'à partir d'un conteneur, pas des paramètres. Vous devez getParameterobtenir des paramètres.
Wouter J

Quand j'essaye, $this->getContainer()->getParameter('api_user');j'obtiens une erreur fatale: Appel à la méthode indéfinie ..Longpath .. \ Controller :: getContainer ().
Bohr

1
@Bohr désolé, version différente de Symfony2. J'ai modifié ma réponse - vérifiez-la maintenant;)
Vitalii Zurian

2
L'URL de la documentation est maintenant symfony.com/doc/2.7/components/dependency_injection/…
SilvioQ

Symfony 2.7 et plus récent: $this->hasParameter()ne fonctionne pas encore.
Saman Mohamadi

23

La manière propre - 2018+, Symfony 3.4+

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

Au lieu d'utiliser l'anti-modèle de localisateur de conteneurs et de services / paramètres, vous pouvez passer des paramètres à la classe via son constructeur . Ne vous inquiétez pas, ce n'est pas un travail fastidieux, mais plutôt une approche unique et oublie .

Comment le configurer en 2 étapes?

1. app/config/services.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. Quelconque 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

C'est ce qu'on appelle une injection de constructeur sur l' approche du localisateur de services .

Pour en savoir plus à ce sujet, consultez mon article Comment obtenir des paramètres dans Symfony Controller de manière propre .

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


Nouvelle façon minimaliste sur ce sujet: tomasvotruba.cz/blog/2018/11/05/…
Tomáš Votruba

10

Je vous envoie un exemple avec swiftmailer:

parameters.yml

recipients: [email1, email2, email3]

prestations de service:

your_service_name:
        class: your_namespace
        arguments: ["%recipients%"]

la classe du service:

protected $recipients;

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

8

Dans Symfony 4, vous pouvez utiliser ParameterBagInterface:

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

et en app/config/services.yaml:

parameters:
    locale: 'en'
    dir: '%kernel.project_dir%'

Cela fonctionne pour moi dans les classes de contrôleur et de formulaire. Plus de détails peuvent être trouvés dans le blog Symfony .


1
Passer un sac de paramètres entiers, c'est comme passer un conteneur entier. Cela n'a de sens que dans «si un service particulier a besoin de beaucoup de paramètres de conteneur» (cité dans l'article)
Tomáš Votruba

alors, voulez-vous dire en passant tout le paramètre cause un problème de performance?
ghazaleh javaheri

C'est l'une des raisons, mais surtout pour la lisibilité. Si je vois le nom du paramètre, $meetupApiKeyje sais à quoi m'attendre un peu mieux que dans$parameterBag
Tomáš Votruba


0

Dans Symfony 4.3.1, j'utilise ceci:

services.yaml

HTTP_USERNAME: 'admin'
HTTP_PASSWORD: 'password123'

FrontController.php

$username = $this->container->getParameter('HTTP_USERNAME');
$password = $this->container->getParameter('HTTP_PASSWORD');

Ne fonctionne pas dans 4.8. Êtes-vous sûr que cela a fonctionné un jour?
Ricardo Martins

J'ai vraiment oublié ça mais oui ça a probablement fonctionné car je n'ai posté que des trucs testés!
Achraf JEDAY

1
Désolé, Acharaf. Je ne sais pas, mais n'a pas fonctionné dans mon contrôleur. À l'intérieur de votre contrôleur, vous pouvez appeler getParameter directement, sans DI. À savoir: $this->getParameter('foo'). C'est ce que j'ai fait pour le faire fonctionner dans SF 4.8.
Ricardo Martins

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.