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?

Bohr
la source

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');
Vitalii Zurian
la source
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 ...)).

Tomáš Votruba
la source
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;
}
Gravitty
la source
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 .

ghazaleh javaheri
la source
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');
Achraf JEDAY
la source
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