Come posso leggere le impostazioni di configurazione da Symfony2 config.yml?


191

Ho aggiunto un'impostazione al mio file config.yml in quanto tale:

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

Per la mia vita, non riesco a capire come leggerlo in una variabile. Ho provato qualcosa di simile in uno dei miei controller:

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

Ma ricevo un errore che dice:

È necessario definire il parametro "contact_email".

Ho svuotato la cache, ho anche cercato ovunque la documentazione del sito ricaricato di Symfony2, ma non riesco a scoprire come farlo.

Probabilmente è troppo stanco per capirlo adesso. Qualcuno può aiutare con questo?

Risposte:


194

Invece di definire contact_emailall'interno app.config, definiscilo in una parametersvoce:

parameters:
    contact_email: somebody@gmail.com

Dovresti trovare che la chiamata che stai effettuando nel controller ora funziona.


4
Come funzionerebbe con gli ambienti Dev / Prod? Quindi per i test voglio che le e-mail vengano inviate a una e-mail di prova e la produzione riceverà un'altra e
Phill Pafford,

2
@Phill: Se stai usando lo swiftmailer standard nel tuo symfony2, puoi usare le seguenti impostazioni nel tuo config_dev.yml: swiftmailer: delivery_address: dev@example.com Puoi trovare maggiori informazioni nel ricettario di Symfony2
Pierre,

4
Devo iniettare la classe contenitore ovunque (controller, entità, classe) quando uso questa istruzione $ this-> container-> getParameter ('contact_email'); ? o c'è un modo più semplice per farlo senza iniettare la classe container?
webblover,

1
Secondo questa soluzione come posso accedere alle proprietà nidificate?
Ousmane,

1
@webblover Basta inserire il parametro stesso usando la %parameter_name%- notazione (in YAML)
MauganRa

173

Mentre la soluzione per spostare il contact_emailto parameters.ymlè facile, come proposto in altre risposte, ciò può facilmente ingombrare il tuo file di parametri se gestisci molti bundle o se gestisci blocchi di configurazione nidificati.

  • Innanzitutto, risponderò rigorosamente alla domanda.
  • Successivamente, fornirò un approccio per ottenere quelle configurazioni dai servizi senza mai passare attraverso uno spazio comune come parametri.

PRIMO APPROCCIO: blocco di configurazione separato, ottenendolo come parametro

Con un'estensione ( ulteriori informazioni sulle estensioni qui ) è possibile mantenerlo facilmente "separato" in diversi blocchi nel config.ymle quindi iniettarlo come parametro ottenibile dal controller.

All'interno della tua classe Extension all'interno della DependencyInjectiondirectory scrivi questo:

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
    }

Quindi nel tuo config.yml, config_dev.yml e così puoi impostare

my_nice_project:
    contact_email: someone@example.com

Per essere in grado di elaborare ciò config.ymlall'interno del tuo MyNiceBundleExtension, avrai anche bisogno di una Configurationclasse nello stesso spazio dei nomi:

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

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

        return $treeBuilder;
    }
}

Quindi è possibile ottenere la configurazione dal controller, come desiderato nella domanda originale, ma mantenendo parameters.ymlpulito e impostandolo config.ymlnelle sezioni separate:

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

SECONDO APPROCCIO: blocco di configurazione separato, iniettando la configurazione in un servizio

Per i lettori alla ricerca di qualcosa di simile ma per ottenere la configurazione da un servizio, esiste anche un modo migliore che non ingombra mai lo spazio comune "paramaters" e non ha nemmeno bisogno containerdi essere passato al servizio (passare l'intero contenitore è pratica evitare).

Questo trucco sopra "inietta" ancora nello spazio dei parametri della tua configurazione.

Tuttavia, dopo aver caricato la definizione del servizio, è possibile aggiungere una chiamata di metodo come ad esempio setConfig()che inietta quel blocco solo al servizio.

Ad esempio, nella classe Extension:

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

Quindi nel tuo services.ymldefinisci il tuo servizio come al solito, senza alcun cambiamento assoluto:

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

E poi nella tua SillyManagerclasse, aggiungi semplicemente il metodo:

class SillyManager
{
    private $contact_email;

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

Si noti che questo funziona anche per le matrici anziché per i valori scalari! Immagina di configurare una coda di coniglio e di avere bisogno di host, utente e password:

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

Ovviamente devi cambiare il tuo albero, ma poi puoi fare:

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

e poi nel servizio fai:

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

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

Spero che questo ti aiuti!


Se vi state chiedendo cosa c'è di diverso tra il primo approccio e la relativa documentazione, è che i valori di configurazione vengono convertiti in parametri nel MyNiceProjectExtension->load()metodo con questa linea: $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ]);. Grazie Xavi!
jxmallett,

Risposta perfetta, vergogna symfony non ti consente di accedere alla configurazione allo stesso modo dei parametri.
Martin Lyne,

Questa è una buona risposta, ma espone il modo ottuso di Symfony di "configurare" un'applicazione. Qual è il punto di avere file di configurazione di ambiente arbitrari quando devi scrivere e invocare servizi specifici per accedervi. Qualcuno di Symfony non si è seduto lì e ha realizzato, 'Forse gli sviluppatori vorrebbero davvero fornire valori specifici per l'ambiente nelle loro applicazioni a cui possono accedere' Tipo di file point of config, non è vero? Stanno seguendo il modello di design "STKTFANREO": "Imposta le manopole su F'd e strappale"
eggmatters

Ha diverse applicazioni, specialmente nella distribuzione di test automatici paralleli, e specialmente quando un team sviluppa un pacchetto che è principalmente un modello o una logica che viene utilizzato da molti altri team in diverse applicazioni, ad esempio un'applicazione che è un front-end dell'utente, un altro che è un fronte Web del pannello di amministrazione e un altro che è un'API REST. Ognuna di queste è un'applicazione diversa disposta a configurare in modo diverso. Ciò viene moltiplicato per diversi ambienti (produzione, pre-produzione, test, sviluppo, ecc.). Ciò produce facilmente in 12 o 15 configurazioni in una singola azienda.
Xavi Montero,

@XaviMontero Ho seguito le tue istruzioni SECONDO APPROCCIO: e quando var_dump il $ this-> contact_email o aggiungi un'uscita () nella funzione setConfig () non esce. Sembra che setConfig non venga chiamato
user742736

35

Devo aggiungere alla risposta di Douglas, puoi accedere alla configurazione globale, ma symfony traduce alcuni parametri, ad esempio:

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

siamo

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

È possibile utilizzare var_dump per cercare una chiave o un valore specificati.


17

Per poter esporre alcuni parametri di configurazione per il pacchetto, consultare la documentazione per farlo. È abbastanza facile da fare :)

Ecco il link: Come esporre una configurazione semantica per un pacchetto


Onestamente, questa domanda è stata posta oltre 2 anni fa, allora, l'articolo sopra non esisteva.
josef.van.niekerk,

10
Sono d'accordo con questa affermazione. Ho impostato la risposta nel caso in cui qualcuno abbia aperto questo articolo al giorno d'oggi. Grazie per il voto negativo - mi hai reso felice.
Nikola Petkanski,

Mi scuso, ora che ci penso, il mio downvote non è stato richiesto. Apprezzo il tuo contributo, ho provato a votare ma SO non lo consente più. Il link è molto utile e sono sicuro che altre persone ne trarranno beneficio! Forse l'amministratore può aiutare a cambiare il mio downvote ???
josef.van.niekerk,

Credo che puoi fare di nuovo clic per annullare.
Nikola Petkanski,

Non puoi annullare il tuo voto più di X (5?) Minuti dopo averlo fatto o fino a quando il messaggio non viene modificato
cheesemacfly


3

Ho imparato in modo semplice dall'esempio di codice di http://tutorial.symblog.co.uk/

1) notare ZendeskBlueFormBundle e la posizione del file

# myproject/app/config/config.yml

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

framework:

2) notare Zendesk_BlueForm.emails.contact_email e posizione del file

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

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

3) nota come ottengo in $ client e posizione del file del controller

# 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"));
    ...
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.