¿Cómo leo desde los parámetros.yml en un controlador en Symfony2?

146

He puesto un par de variables personalizadas en mi aplicación / config / parameters.yml.

parameters:
    api_pass: apipass
    api_user: apiuser

Necesito acceder a estos desde mi controlador, y he intentado buscarlos con

$this->get('api_user');

desde mi archivo controlador. Cuando intento esto, recibo este mensaje de error:

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

¿Cuál es la forma correcta de hacer esto?

Bohr
fuente

Respuestas:

296

En Symfony 2.6 y versiones anteriores , para obtener un parámetro en un controlador, primero debe obtener el contenedor y luego el parámetro necesario.

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

Este capítulo de documentación lo explica.

Mientras que el $this->get()método en un controlador cargará un servicio ( doc )

En Symfony 2.7 y versiones más recientes , para obtener un parámetro en un controlador, puede usar lo siguiente:

$this->getParameter('api_user');
Vitalii Zurian
fuente
3
Tenga en cuenta que el getmétodo en el controlador también usa el contenedor, pero solo puede obtener servicios de un contenedor, no parámetros. Necesitas getParameterobtener parámetros.
Wouter J
Cuando lo intento $this->getContainer()->getParameter('api_user');me sale un error grave: Llame al método indefinido .. Longpath .. \ Controller :: getContainer ().
Bohr
1
@Bohr lo siento, una versión diferente de Symfony2. He editado mi respuesta, compruébalo ahora;)
Vitalii Zurian
2
La URL para la documentación ahora es symfony.com/doc/2.7/components/dependency_injection/…
SilvioQ
Symfony 2.7 y más reciente: $this->hasParameter()aún no funciona.
Saman Mohamadi
23

The Clean Way - 2018+, Symfony 3.4+

Desde 2017 y Symfony 3.3 + 3.4 hay una forma mucho más limpia: fácil de configurar y usar.

En lugar de utilizar el antipatrón de contenedor y servicio / localizador de parámetros, puede pasar parámetros a la clase a través de su constructor . No se preocupe, no es un trabajo que requiera mucho tiempo, sino más bien configurar una vez y olvidar el enfoque.

¿Cómo configurarlo en 2 pasos?

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

¡Actualización instantánea lista!

En caso de que use un enfoque anterior, puede automatizarlo con Rector .

Lee mas

Esto se llama inyección de constructor sobre el enfoque del localizador de servicios .

Para leer más sobre esto, consulte mi publicación Cómo obtener el parámetro en Symfony Controller the Clean Way .

(Está probado y lo mantengo actualizado para la nueva versión principal de Symfony (5, 6 ...)).

Tomáš Votruba
fuente
Nueva forma minimalista sobre este tema: tomasvotruba.cz/blog/2018/11/05/…
Tomáš Votruba
10

Te envío un ejemplo con swiftmailer:

parámetros.yml

recipients: [email1, email2, email3]

servicios:

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

la clase del servicio:

protected $recipients;

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

En Symfony 4, puedes usar 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');
        // ...
    }
}

y en app/config/services.yaml:

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

A mí me funciona tanto en el controlador como en las clases de formulario. Se pueden encontrar más detalles en el blog de Symfony .

ghazaleh javaheri
fuente
1
Pasar una bolsa de parámetros completa es como pasar un contenedor completo. Tiene sentido solo en "si algún servicio en particular necesita muchos parámetros de contenedor" (citado de la publicación)
Tomáš Votruba
Entonces, ¿te refieres a que pasar todo el parámetro causa un problema en el rendimiento?
ghazaleh javaheri
Esa es una de las razones, pero principalmente por la legibilidad. Si veo a nombre del parámetro $meetupApiKeyque sé qué esperar un poco mejor que en$parameterBag
Tomáš Votruba
0

En Symfony 4.3.1 uso esto:

services.yaml

HTTP_USERNAME: 'admin'
HTTP_PASSWORD: 'password123'

FrontController.php

$username = $this->container->getParameter('HTTP_USERNAME');
$password = $this->container->getParameter('HTTP_PASSWORD');
Achraf JEDAY
fuente
No funciona en 4.8. ¿Estás seguro de que funcionó algún día?
Ricardo Martins
Realmente me olvidé de esto, pero sí, probablemente funcionó porque publiqué solo cosas probadas.
Achraf JEDAY
1
Lo siento, Acharaf. No lo sé, pero no funcionó en mi controlador. Dentro de su controlador puede llamar a getParameter directamente, sin DI. Es decir: $this->getParameter('foo'). Eso es lo que hice para que funcione en SF 4.8.
Ricardo Martins