Jak czytać z parameters.yml w kontrolerze w symfony2?

146

Umieściłem kilka zmiennych niestandardowych w moim app / config / parameters.yml.

parameters:
    api_pass: apipass
    api_user: apiuser

Muszę uzyskać do nich dostęp z mojego kontrolera i próbowałem je pobrać za pomocą

$this->get('api_user');

z mojego pliku kontrolera. Kiedy próbuję, otrzymuję ten komunikat o błędzie:

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

Jaki jest właściwy sposób, aby to zrobić?

Bohr
źródło

Odpowiedzi:

296

W Symfony 2.6 i starszych wersjach , aby uzyskać parametr w kontrolerze - należy najpierw pobrać kontener, a następnie - potrzebny parametr.

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

Ten rozdział dokumentacji wyjaśnia to.

$this->get()Metoda While w kontrolerze załaduje usługę ( doc )

W Symfony 2.7 i nowszych wersjach , aby uzyskać parametr w kontrolerze, możesz użyć:

$this->getParameter('api_user');
Vitalii Zurian
źródło
3
Zwróć uwagę, że getmetoda w kontrolerze również używa kontenera, ale może pobierać usługi tylko z kontenera, a nie parametry. Musisz getParameteruzyskać parametry.
Wouter J
Kiedy próbuję $this->getContainer()->getParameter('api_user');, otrzymuję błąd krytyczny: wywołanie niezdefiniowanej metody ..Longpath .. \ Controller :: getContainer ().
Bohr
1
@Bohr przepraszam, inna wersja Symfony2. Zredagowałem odpowiedź - sprawdź teraz;)
Vitalii Zurian
2
Adres URL dokumentacji to teraz symfony.com/doc/2.7/components/dependency_injection/ ...
SilvioQ
Symfony 2.7 i nowsze: $this->hasParameter()jeszcze nie działa.
Saman Mohamadi
23

Czysty sposób - 2018+, Symfony 3.4+

Od 2017 i Symfony 3.3 + 3.4 istnieje znacznie czystszy sposób - łatwy w konfiguracji i obsłudze.

Zamiast używać kontenera i anty-wzorca lokalizatora usługi / parametrów, możesz przekazać parametry do klasy za pośrednictwem jej konstruktora . Nie martw się, nie jest to czasochłonna praca, ale raczej konfiguracja raz i zapomnij .

Jak to ustawić w 2 krokach?

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

Gotowe do natychmiastowej aktualizacji!

Jeśli korzystasz ze starszego podejścia, możesz je zautomatyzować za pomocą Rectora .

Czytaj więcej

Nazywa się to podejściem wstrzykiwania konstruktora do lokalizatora usług .

Aby dowiedzieć się więcej na ten temat, zajrzyj do mojego postu Jak uzyskać parametry w kontrolerze Symfony w czysty sposób .

(Jest przetestowany i aktualizuję go pod kątem nowej głównej wersji Symfony (5, 6 ...)).

Tomáš Votruba
źródło
Nowy minimalistyczny sposób na ten temat: tomasvotruba.cz/blog/2018/11/05/...
Tomáš Votruba
10

Przesyłam Ci przykład ze swiftmailer:

parameters.yml

recipients: [email1, email2, email3]

usługi:

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

klasa usługi:

protected $recipients;

public function __construct($recipients)
{
    $this->recipients = $recipients;
}
Gravitty
źródło
8

W Symfony 4 możesz użyć 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');
        // ...
    }
}

i w app/config/services.yaml:

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

U mnie działa zarówno w klasach kontrolerów, jak i formularzy. Więcej szczegółów można znaleźć na blogu Symfony .

ghazaleh javaheri
źródło
1
Przekazywanie woreczka z parametrami jest jak przekazywanie całego kontenera. Ma to sens tylko w „jeśli jakaś konkretna usługa wymaga wielu parametrów kontenera” (cytat z postu)
Tomáš Votruba
tak, czy masz na myśli przekazanie całego parametru powoduje problem w wydajności?
ghazaleh javaheri
To jeden z powodów, ale głównie ze względu na czytelność. Jeśli widzę nazwę parametru $meetupApiKey, wiem, czego się spodziewać nieco lepiej niż w$parameterBag
Tomáš Votruba
0

W Symfony 4.3.1 używam tego:

services.yaml

HTTP_USERNAME: 'admin'
HTTP_PASSWORD: 'password123'

FrontController.php

$username = $this->container->getParameter('HTTP_USERNAME');
$password = $this->container->getParameter('HTTP_PASSWORD');
Achraf JEDAY
źródło
Nie działa w 4.8. Czy na pewno kiedyś zadziałało?
Ricardo Martins
Naprawdę o tym zapomniałem, ale tak, prawdopodobnie zadziałało, ponieważ publikuję tylko przetestowane rzeczy!
Achraf JEDAY
1
Przepraszam, Acharaf. Nie wiem, ale nie działało na moim kontrolerze. W kontrolerze możesz bezpośrednio wywołać getParameter, bez DI. Tj $this->getParameter('foo'). Właśnie to zrobiłem, aby działało w SF 4.8.
Ricardo Martins