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.