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.