Wie lese ich Konfigurationseinstellungen aus Symfony2 config.yml?

191

Ich habe meiner Datei config.yml eine Einstellung als solche hinzugefügt:

app.config:
    contact_email: somebody@gmail.com
    ...

Für mein Leben kann ich nicht herausfinden, wie ich es in eine Variable einlesen kann. Ich habe so etwas in einem meiner Controller versucht:

$recipient =
$this->container->getParameter('contact_email');

Aber ich bekomme eine Fehlermeldung:

Der Parameter "contact_email" muss definiert werden.

Ich habe meinen Cache geleert und auch überall in der neu geladenen Site-Dokumentation zu Symfony2 nachgesehen, kann aber nicht herausfinden, wie das geht.

Wahrscheinlich einfach zu müde, um das jetzt herauszufinden. Kann mir jemand dabei helfen?

josef.van.niekerk
quelle

Antworten:

194

Anstatt contact_emailinnerhalb zu app.configdefinieren, definieren Sie es in einem parametersEintrag:

parameters:
    contact_email: somebody@gmail.com

Sie sollten feststellen, dass der Anruf, den Sie in Ihrem Controller tätigen, jetzt funktioniert.

Douglas Greenshields
quelle
4
Wie würde dies mit den Dev / Prod-Umgebungen funktionieren? Zum Testen möchte ich, dass die E-Mails an eine Test-E-Mail
gesendet werden
2
@Phill: Wenn Sie den Standard-Swiftmailer in Ihrem symfony2 verwenden, können Sie die folgende Einstellung in Ihrer config_dev.yml verwenden: swiftmailer: delivery_address: [email protected] Weitere Informationen finden Sie im Symfony2-Kochbuch
Pierre
4
Sollte ich eine Containerklasse überall einfügen (Controller, Entität, Klasse), wenn ich diese Anweisung verwende $ this-> container-> getParameter ('contact_email'); ? oder gibt es eine einfachere Möglichkeit, dies zu tun, ohne die Containerklasse zu injizieren?
Webblover
1
Wie kann ich gemäß dieser Lösung auf verschachtelte Eigenschaften zugreifen?
Ousmane
1
@weblblover Fügen Sie einfach den Parameter selbst mit der %parameter_name%- Notation (in YAML)
MauganRa
173

Wie in anderen Antworten vorgeschlagen contact_email, parameters.ymlist die Lösung des Verschiebens von zwar einfach, kann jedoch Ihre Parameterdatei leicht überladen, wenn Sie mit vielen Bundles oder verschachtelten Konfigurationsblöcken arbeiten.

  • Zuerst werde ich die Frage streng beantworten.
  • Später werde ich einen Ansatz geben, um diese Konfigurationen von Diensten abzurufen, ohne jemals einen gemeinsamen Raum als Parameter zu durchlaufen.

ERSTER ANSATZ: Getrennter Konfigurationsblock, der als Parameter abgerufen wird

Mit einer Erweiterung ( mehr zu Erweiterungen hier ) können Sie diese einfach in verschiedene Blöcke in der "trennen" config.ymlund diese dann als Parameter einfügen, der vom Controller abgerufen werden kann.

DependencyInjectionSchreiben Sie in Ihrer Erweiterungsklasse im Verzeichnis Folgendes:

class MyNiceProjectExtension extends Extension
{
    public function load( array $configs, ContainerBuilder $container )
    {
        // The next 2 lines are pretty common to all Extension templates.
        $configuration = new Configuration();
        $processedConfig = $this->processConfiguration( $configuration, $configs );

        // This is the KEY TO YOUR ANSWER
        $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ] );

        // Other stuff like loading services.yml
    }

Dann in Ihrer config.yml, config_dev.yml und so können Sie einstellen

my_nice_project:
    contact_email: someone@example.com

Um dies config.ymlin Ihrem verarbeiten zu können, MyNiceBundleExtensionbenötigen Sie außerdem eine ConfigurationKlasse im selben Namespace:

class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root( 'my_nice_project' );

        $rootNode->children()->scalarNode( 'contact_email' )->end();

        return $treeBuilder;
    }
}

Dann können Sie die Konfiguration von Ihrem Controller erhalten, wie Sie es in Ihrer ursprünglichen Frage gewünscht haben, aber die Konfiguration parameters.ymlsauber halten und in den config.ymlgetrennten Abschnitten einstellen :

$recipient = $this->container->getParameter( 'my_nice_project.contact_email' );

ZWEITER ANSATZ: Separater Konfigurationsblock, der die Konfiguration in einen Dienst einfügt

Für Leser, die nach etwas Ähnlichem suchen, aber die Konfiguration von einem Dienst erhalten möchten, gibt es eine noch schönere Möglichkeit, die den gemeinsamen Raum der "Parameter" niemals überfüllt und nicht einmal containeran den Dienst übergeben werden muss (das Übergeben des gesamten Containers ist üblich vermeiden).

Dieser Trick oben "injiziert" immer noch in den Parameterraum Ihrer Konfiguration.

Trotzdem können Sie nach dem Laden Ihrer Definition des Dienstes einen Methodenaufruf wie beispielsweise hinzufügen setConfig(), der diesen Block nur in den Dienst einfügt.

Zum Beispiel in der Erweiterungsklasse:

class MyNiceProjectExtension extends Extension
{
    public function load( array $configs, ContainerBuilder $container )
    {
        $configuration = new Configuration();
        $processedConfig = $this->processConfiguration( $configuration, $configs );

        // Do not add a paramater now, just continue reading the services.
        $loader = new YamlFileLoader( $container, new FileLocator( __DIR__ . '/../Resources/config' ) );
        $loader->load( 'services.yml' );

        // Once the services definition are read, get your service and add a method call to setConfig()
        $sillyServiceDefintion = $container->getDefinition( 'my.niceproject.sillymanager' );
        $sillyServiceDefintion->addMethodCall( 'setConfig', array( $processedConfig[ 'contact_email' ] ) );
    }
}

Dann services.ymldefinieren Sie in Ihrem Dienst Ihren Service wie gewohnt, ohne absolute Änderung:

services:
    my.niceproject.sillymanager:
        class: My\NiceProjectBundle\Model\SillyManager
        arguments: []

Und dann SillyManagerfügen Sie in Ihrer Klasse einfach die Methode hinzu:

class SillyManager
{
    private $contact_email;

    public function setConfig( $newConfigContactEmail )
    {
        $this->contact_email = $newConfigContactEmail;
    }
}

Beachten Sie, dass dies auch für Arrays anstelle von Skalarwerten funktioniert! Stellen Sie sich vor, Sie konfigurieren eine Kaninchenwarteschlange und benötigen Host, Benutzer und Kennwort:

my_nice_project:
    amqp:
        host: 192.168.33.55
        user: guest
        password: guest

Natürlich müssen Sie Ihren Baum ändern, aber dann können Sie Folgendes tun:

$sillyServiceDefintion->addMethodCall( 'setConfig', array( $processedConfig[ 'amqp' ] ) );

und dann im Service tun:

class SillyManager
{
    private $host;
    private $user;
    private $password;

    public function setConfig( $config )
    {
        $this->host = $config[ 'host' ];
        $this->user = $config[ 'user' ];
        $this->password = $config[ 'password' ];
    }
}

Hoffe das hilft!

Xavi Montero
quelle
Wenn Sie sich fragen, was sich zwischen dem ersten Ansatz und der Dokumentation unterscheidet, werden die Konfigurationswerte in der MyNiceProjectExtension->load()Methode mit der folgenden Zeile in Parameter konvertiert : $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ]);. Danke Xavi!
jxmallett
Perfekte Antwort, Scham Symfony lässt Sie nicht auf die Konfiguration zugreifen, wie es Parameter tut.
Martin Lyne
Dies ist eine gute Antwort, zeigt jedoch Symfony's stumpfe Art, eine Anwendung zu "konfigurieren". Was bringt es, beliebige Umgebungskonfigurationsdateien zu haben, wenn Sie bestimmte Dienste schreiben und aufrufen müssen, um darauf zuzugreifen? Hat nicht jemand bei Symfony dort gesessen und festgestellt: "Vielleicht möchten Entwickler tatsächlich umgebungsspezifische Werte in ihren Anwendungen bereitstellen, auf die sie zugreifen können." Sie folgen dem Designmuster "STKTFANREO": "Stellen Sie die Knöpfe auf F'd und reißen Sie sie ab"
Eggmatters
Es verfügt über mehrere Anwendungen, insbesondere für die Bereitstellung parallelisierter automatischer Tests, und insbesondere dann, wenn ein Team ein Bundle entwickelt, das hauptsächlich aus einem Modell oder einer Logik besteht und von mehreren anderen Teams in verschiedenen Anwendungen verwendet wird, z. B. einer Anwendung, die ein Benutzer-Front-End ist. Eine andere ist eine Webfront des Admin-Panels und eine andere eine REST-API. Jede davon ist eine andere Anwendung, die bereit ist, anders zu konfigurieren. Dies wird mit mehreren Umgebungen multipliziert (Produktion, Vorproduktion, Test, Entwicklung usw.). Dies ergibt leicht 12 oder 15 Konfigurationen in einem einzigen Unternehmen.
Xavi Montero
@XaviMontero Ich habe Ihre Anweisung befolgt ZWEITER ANSATZ: und wenn var_dump die $ this-> contact_email oder ein exit () in der Funktion setConfig () hinzufügt, wird es nicht beendet. Es sieht so aus, als würde setConfig nicht aufgerufen
user742736
35

Ich muss der Antwort von Douglas hinzufügen, dass Sie auf die globale Konfiguration zugreifen können, aber symfony übersetzt einige Parameter, zum Beispiel:

# config.yml
... 
framework:
    session:
        domain: 'localhost'
...

sind

$this->container->parameters['session.storage.options']['domain'];

Mit var_dump können Sie einen bestimmten Schlüssel oder Wert suchen.

Felipe Buccioni
quelle
17

Um einige Konfigurationsparameter für Ihr Bundle verfügbar machen zu können, sollten Sie dazu die Dokumentation konsultieren. Es ist ziemlich einfach zu machen :)

Hier ist der Link: So legen Sie eine semantische Konfiguration für ein Bundle offen

Nikola Petkanski
quelle
Ehrlich gesagt wurde diese Frage vor über 2 Jahren gestellt, damals existierte der obige Artikel nicht.
Josefvan.niekerk
10
Ich stimme dieser Aussage zu. Ich habe die Antwort für den Fall festgelegt, dass jemand diesen Artikel heutzutage öffnet. Danke für die negative Bewertung - du hast meinen Tag gemacht.
Nikola Petkanski
Ich entschuldige mich, jetzt wo ich darüber nachdenke, war meine Ablehnung unangebracht. Ich schätze Ihren Beitrag, ich habe versucht zu stimmen, aber SO erlaubt es nicht mehr. Der Link ist sehr hilfreich und ich bin sicher, dass andere Leute davon profitieren werden! Vielleicht kann der Administrator helfen, meine Downvote zu ändern ???
Josefvan.niekerk
Ich glaube, Sie können erneut klicken, um rückgängig zu machen.
Nikola Petkanski
Sie können Ihre Abstimmung nicht länger als X (5?) Minuten rückgängig machen, nachdem Sie dies getan haben oder bis die Nachricht bearbeitet wurde
cheesemacfly
3

Ich habe einen einfachen Weg aus dem Codebeispiel von http://tutorial.symblog.co.uk/ gelernt.

1) Beachten Sie das ZendeskBlueFormBundle und den Speicherort der Datei

# myproject/app/config/config.yml

imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: @ZendeskBlueFormBundle/Resources/config/config.yml }

framework:

2) Beachten Sie Zendesk_BlueForm.emails.contact_email und den Speicherort der Datei

# myproject/src/Zendesk/BlueFormBundle/Resources/config/config.yml

parameters:
    # Zendesk contact email address
    Zendesk_BlueForm.emails.contact_email: dunnleaddress@gmail.com

3) Beachten Sie, wie ich es in $ Client und Dateispeicherort des Controllers bekomme

# myproject/src/Zendesk/BlueFormBundle/Controller/PageController.php

    public function blueFormAction($name, $arg1, $arg2, $arg3, Request $request)
    {
    $client = new ZendeskAPI($this->container->getParameter("Zendesk_BlueForm.emails.contact_email"));
    ...
    }
Dung
quelle