Wie lese ich aus parameters.yml in einem Controller in symfony2?

146

Ich habe einige benutzerdefinierte Variablen in meine app / config / parameters.yml eingefügt.

parameters:
    api_pass: apipass
    api_user: apiuser

Ich muss von meinem Controller aus auf diese zugreifen und habe versucht, sie mit abzurufen

$this->get('api_user');

aus meiner Controller-Datei. Wenn ich das versuche, erhalte ich folgende Fehlermeldung:

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

Was ist der richtige Weg, um dies zu tun?

Bohr
quelle

Antworten:

296

In Symfony 2.6 und älteren Versionen sollten Sie zum Abrufen eines Parameters in einem Controller zuerst den Container und dann den erforderlichen Parameter abrufen.

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

Dieses Dokumentationskapitel erklärt es.

Während die $this->get()Methode in einem Controller einen Dienst lädt ( doc )

In Symfony 2.7 und neueren Versionen können Sie Folgendes verwenden, um einen Parameter in einem Controller abzurufen:

$this->getParameter('api_user');
Vitalii Zurian
quelle
3
Beachten Sie, dass die getMethode in der Steuerung auch den Container verwendet, jedoch nur Dienste von einem Container abrufen kann, keine Parameter. Sie müssen getParameterParameter erhalten.
Wouter J
Wenn ich es versuche, $this->getContainer()->getParameter('api_user');erhalte ich einen schwerwiegenden Fehler: Aufruf der undefinierten Methode ..Longpath .. \ Controller :: getContainer ().
Bohr
1
@Bohr sorry, andere Version von Symfony2. Ich habe meine Antwort bearbeitet - überprüfe sie jetzt;)
Vitalii Zurian
2
Die URL für die Dokumentation lautet jetzt symfony.com/doc/2.7/components/dependency_injection/…
SilvioQ
Symfony 2.7 und neuer: $this->hasParameter()funktioniert noch nicht.
Saman Mohamadi
23

The Clean Way - 2018+, Symfony 3.4+

Seit 2017 und Symfony 3.3 + 3.4 gibt es viel sauberere Wege - einfach einzurichten und zu verwenden.

Anstatt das Anti-Pattern für Container und Service / Parameter Locator zu verwenden, können Sie Parameter über den Konstruktor an die Klasse übergeben . Keine Sorge, es ist keine zeitaufwändige Arbeit, sondern ein einmaliges Einrichten und Vergessen des Ansatzes.

Wie richte ich es in 2 Schritten ein?

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

Sofortiges Upgrade bereit!

Wenn Sie einen älteren Ansatz verwenden, können Sie ihn mit Rector automatisieren .

Weiterlesen

Dies wird als Konstruktorinjektion über den Dienstlokalisierungsansatz bezeichnet .

Weitere Informationen hierzu finden Sie in meinem Beitrag So erhalten Sie Parameter in Symfony Controller auf saubere Weise .

(Es wurde getestet und ich halte es für die neue Symfony-Hauptversion (5, 6 ...) auf dem neuesten Stand.)

Tomáš Votruba
quelle
Neuer minimalistischer Weg zu diesem Thema: tomasvotruba.cz/blog/2018/11/05/…
Tomáš Votruba
10

Ich sende Ihnen ein Beispiel mit swiftmailer:

parameters.yml

recipients: [email1, email2, email3]

Dienstleistungen:

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

die Klasse des Dienstes:

protected $recipients;

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

In Symfony 4 können Sie Folgendes verwenden 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');
        // ...
    }
}

und in app/config/services.yaml:

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

Es funktioniert für mich sowohl in Controller- als auch in Formularklassen. Weitere Details finden Sie im Symfony-Blog .

ghazaleh javaheri
quelle
1
Das Übergeben eines ganzen Parameterbeutels ist wie das Übergeben eines ganzen Containers. Es ist nur in "wenn ein bestimmter Dienst viele Containerparameter benötigt" (zitiert aus dem Beitrag)
Tomáš Votruba
Meinen Sie damit, dass das Übergeben ganzer Parameter zu Leistungsproblemen führt?
Ghazaleh Javaheri
Das ist einer der Gründe, aber hauptsächlich für die Lesbarkeit. Wenn ich den Parameternamen $meetupApiKeysehe, weiß ich, was mich etwas besser erwartet als in$parameterBag
Tomáš Votruba
0

In Symfony 4.3.1 verwende ich Folgendes:

services.yaml

HTTP_USERNAME: 'admin'
HTTP_PASSWORD: 'password123'

FrontController.php

$username = $this->container->getParameter('HTTP_USERNAME');
$password = $this->container->getParameter('HTTP_PASSWORD');
Achraf JEDAY
quelle
Funktioniert nicht in 4.8. Bist du sicher, dass es eines Tages funktioniert hat?
Ricardo Martins
Ich habe das wirklich vergessen, aber ja, es hat wahrscheinlich funktioniert, weil ich nur getestete Sachen poste!
Achraf JEDAY
1
Entschuldigung, Acharaf. Ich weiß es nicht, habe aber in meinem Controller nicht funktioniert. In Ihrem Controller können Sie getParameter ohne DI direkt aufrufen. Dh : $this->getParameter('foo'). Das habe ich getan, damit es in SF 4.8 funktioniert.
Ricardo Martins