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?

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

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


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

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 .


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

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.