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?

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');

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 ...)).


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;
}

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 .


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');

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.