Como faço para ler a partir de parameters.yml em um controlador no symfony2?

146

Eu coloquei algumas variáveis ​​personalizadas no meu app / config / parameters.yml.

parameters:
    api_pass: apipass
    api_user: apiuser

Preciso acessá-los do meu controlador e tentei buscá-los com

$this->get('api_user');

de dentro do meu arquivo do controlador. Quando tento isso, recebo esta mensagem de erro:

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

Qual é a maneira correta de fazer isso?

Bohr
fonte

Respostas:

296

No Symfony 2.6 e versões mais antigas , para obter um parâmetro em um controlador - você deve obter o contêiner primeiro e depois - o parâmetro necessário.

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

Este capítulo da documentação explica isso.

Enquanto o $this->get()método em um controlador carrega um serviço ( doc )

No Symfony 2.7 e em versões mais recentes , para obter um parâmetro em um controlador, você pode usar o seguinte:

$this->getParameter('api_user');
Vitalii Zurian
fonte
3
Observe que o getmétodo no controlador também usa o contêiner, mas ele só pode obter serviços de um contêiner, não de parâmetros. Você precisa getParameterobter parâmetros.
Wouter J
Quando tento $this->getContainer()->getParameter('api_user');obter erro fatal: Ligue para o método indefinido .. Longpath .. \ Controller :: getContainer ().
Bohr
1
@ Bohr desculpe, versão diferente do Symfony2. Eu editei a minha resposta - confira agora;)
Vitalii Zurian
2
O URL para a documentação está agora symfony.com/doc/2.7/components/dependency_injection/...
SilvioQ
Symfony 2.7 e mais recente: $this->hasParameter()ainda não está funcionando.
Saman Mohamadi
23

O Caminho Limpo - 2018+, Symfony 3.4+

Desde 2017 e Symfony 3.3 + 3.4, há uma maneira muito mais limpa - fácil de configurar e usar.

Em vez de usar o contêiner e o antipadrão de localizador de serviço / parâmetro, você pode passar parâmetros para a classe via seu construtor . Não se preocupe, não é um trabalho demorado, mas configure uma vez e esqueça a abordagem.

Como configurá-lo em 2 etapas?

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. Qualquer 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"
    }
}

Pronto para atualização instantânea!

Caso você use uma abordagem mais antiga, você pode automatizá-la com o Rector .

consulte Mais informação

Isso é chamado de abordagem de injeção de construtor sobre localizador de serviços .

Para ler mais sobre isso, confira meu post Como obter parâmetros no Symfony Controller de maneira limpa .

(Ele foi testado e eu o mantenho atualizado para a nova versão principal do Symfony (5, 6 ...)).

Tomáš Votruba
fonte
Nova maneira minimalista sobre este tópico: tomasvotruba.cz/blog/2018/11/05/…
Tomáš Votruba 12/11/2018
10

Envio-lhe um exemplo com o swiftmailer:

parameters.yml

recipients: [email1, email2, email3]

Serviços:

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

a classe do serviço:

protected $recipients;

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

No Symfony 4, você pode usar o 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');
        // ...
    }
}

e em app/config/services.yaml:

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

Funciona para mim nas classes controller e form. Mais detalhes podem ser encontrados no blog do Symfony .

ghazaleh javaheri
fonte
1
Passar um saco de parâmetros inteiros é como passar um recipiente inteiro. Faz sentido apenas em "se algum serviço específico precisa de muita parâmetros recipiente" (citado no post)
Tomáš Votruba
então, você quer dizer que passar todo o parâmetro causa problemas no desempenho?
Ghazaleh javaheri
Essa é uma das razões, mas principalmente pela legibilidade. Se eu $meetupApiKey$parameterBag
vir o
0

No Symfony 4.3.1 eu uso isso:

services.yaml

HTTP_USERNAME: 'admin'
HTTP_PASSWORD: 'password123'

FrontController.php

$username = $this->container->getParameter('HTTP_USERNAME');
$password = $this->container->getParameter('HTTP_PASSWORD');
Achraf JEDAY
fonte
Não funciona no 4.8. Tem certeza de que funcionou algum dia?
Ricardo Martins
Eu realmente esqueci disso, mas sim, provavelmente funcionou porque eu posto apenas coisas testadas!
Achraf JEDAY
1
Desculpe, Acharaf. Não sei, mas não funcionou no meu controlador. Dentro do seu controlador, você pode chamar getParameter diretamente, sem DI. Ou seja: $this->getParameter('foo'). Foi o que fiz para fazê-lo funcionar no SF 4.8.
Ricardo Martins