Bagaimana cara membaca pengaturan konfigurasi dari Symfony2 config.yml?

191

Saya telah menambahkan pengaturan ke file config.yml saya seperti:

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

Untuk kehidupan saya, saya tidak tahu bagaimana membacanya menjadi variabel. Saya mencoba sesuatu seperti ini di salah satu pengendali saya:

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

Tapi saya mendapat pesan kesalahan:

Parameter "contact_email" harus ditentukan.

Saya telah membersihkan cache saya, saya juga mencari di mana-mana di dokumentasi situs Symfony2 yang dimuat kembali, tetapi saya tidak dapat menemukan cara untuk melakukan ini.

Mungkin terlalu lelah untuk memikirkan ini sekarang. Adakah yang bisa membantu dengan ini?

josef.van.niekerk
sumber

Jawaban:

194

Daripada mendefinisikan di contact_emaildalam app.config, mendefinisikannya dalam parametersentri:

parameters:
    contact_email: somebody@gmail.com

Anda seharusnya menemukan panggilan yang Anda buat di dalam pengontrol Anda sekarang berfungsi.

Douglas Greenshields
sumber
4
Bagaimana ini akan bekerja dengan lingkungan Dev / Prod? Jadi untuk pengujian saya ingin email untuk dikirim ke email pengujian dan produksi akan mendapatkan email lain
Phill Pafford
2
@Phill: Jika Anda menggunakan swiftmailer standar di symfony2 Anda, Anda dapat menggunakan pengaturan berikut di config_dev.yml: swiftmailer: delivery_address: [email protected] Anda dapat menemukan informasi lebih lanjut di buku masak Symfony2
Pierre
4
Haruskah saya menyuntikkan kelas wadah di mana-mana (controller, entitas, kelas) ketika saya menggunakan pernyataan ini $ this-> container-> getParameter ('contact_email'); ? atau adakah cara yang lebih sederhana untuk melakukannya tanpa menyuntikkan kelas wadah?
webblover
1
Menurut solusi ini, bagaimana saya bisa mengakses properti bersarang?
Ousmane
1
@webblover Cukup masukkan parameter itu sendiri menggunakan %parameter_name%- notation (dalam YAML)
MauganRa
173

Meskipun solusi memindahkan contact_emailke parameters.ymlmudah, seperti yang diusulkan dalam jawaban lain, itu dapat dengan mudah mengacaukan file parameter Anda jika Anda berurusan dengan banyak bundel atau jika Anda berurusan dengan blok konfigurasi yang bersarang.

  • Pertama, saya akan menjawab pertanyaan itu dengan ketat.
  • Kemudian, saya akan memberikan pendekatan untuk mendapatkan konfigurasi tersebut dari layanan tanpa pernah melewati ruang umum sebagai parameter.

PENDEKATAN PERTAMA: Blok konfigurasi terpisah, menjadikannya sebagai parameter

Dengan ekstensi ( lebih lanjut tentang ekstensi di sini ) Anda dapat menjaga ini dengan mudah "dipisahkan" ke dalam blok yang berbeda di config.ymldan kemudian menyuntikkan itu sebagai parameter gettable dari controller.

Di dalam kelas Ekstensi Anda di dalam DependencyInjectiondirektori tulis ini:

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
    }

Kemudian di config.yml Anda, config_dev.yml dan Anda dapat mengaturnya

my_nice_project:
    contact_email: someone@example.com

Untuk dapat memprosesnya config.ymldi dalam Anda, MyNiceBundleExtensionAnda juga memerlukan Configurationkelas di namespace yang sama:

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

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

        return $treeBuilder;
    }
}

Kemudian Anda bisa mendapatkan konfigurasi dari controller Anda, seperti yang Anda inginkan dalam pertanyaan awal Anda, tetapi tetap parameters.ymlbersihkan, dan atur config.ymldi bagian yang terpisah:

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

PENDEKATAN KEDUA: Blok konfigurasi terpisah, menyuntikkan konfigurasi ke layanan

Untuk pembaca yang mencari sesuatu yang serupa tetapi untuk mendapatkan konfigurasi dari layanan, bahkan ada cara yang lebih baik yang tidak pernah mengacaukan ruang bersama "paramaters" dan bahkan tidak perlu containerdilewatkan ke layanan (melewati seluruh wadah adalah praktik untuk menghindari).

Trik di atas masih "menyuntikkan" ke dalam ruang parameter konfigurasi Anda.

Namun demikian, setelah memuat definisi Anda tentang layanan, Anda dapat menambahkan pemanggilan metode seperti misalnya setConfig()yang menyuntikkan blok itu hanya ke layanan.

Misalnya, di kelas Ekstensi:

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

Kemudian di Anda, services.ymlAnda mendefinisikan layanan Anda seperti biasa, tanpa perubahan mutlak:

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

Dan kemudian di SillyManagerkelas Anda , cukup tambahkan metode:

class SillyManager
{
    private $contact_email;

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

Perhatikan bahwa ini juga berfungsi untuk array alih-alih nilai skalar! Bayangkan Anda mengkonfigurasi antrian kelinci dan memerlukan host, pengguna, dan kata sandi:

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

Tentu saja Anda perlu mengubah Pohon Anda, tetapi kemudian Anda dapat melakukan:

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

dan kemudian di layanan lakukan:

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

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

Semoga ini membantu!

Xavi Montero
sumber
Jika Anda bertanya-tanya apa yang berbeda antara pendekatan pertama dan dokumentasi, itu adalah bahwa nilai-nilai konfigurasi diubah menjadi parameter dalam MyNiceProjectExtension->load()metode dengan baris ini: $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ]);. Terima kasih Xavi!
jxmallett
Jawaban sempurna, symfony malu tidak membiarkan Anda mengakses konfigurasi seperti halnya parameter.
Martin Lyne
Ini adalah jawaban yang baik, tetapi itu mengungkapkan cara tumpul Symfony untuk "mengkonfigurasi" aplikasi. Apa gunanya memiliki file konfigurasi lingkungan sewenang-wenang ketika Anda harus menulis dan meminta layanan khusus untuk mengaksesnya. Bukankah seseorang di Symfony duduk di sana dan menyadari, 'Mungkin pengembang sebenarnya ingin memberikan nilai spesifik lingkungan dalam aplikasi mereka yang dapat mereka akses' Jenis titik file konfigurasi bukan? Mereka mengikuti pola desain "STKTFANREO": "Setel tombol ke F dan rip off"
eggmatters
Ini memiliki beberapa aplikasi, khususnya dalam menyebarkan pengujian otomatis paralel, dan khususnya ketika tim mengembangkan bundel yang terutama model atau logika yang dikonsumsi oleh beberapa tim lain dalam aplikasi yang berbeda, misalnya aplikasi yang merupakan pengguna front-end, satu lagi yang merupakan web panel admin-depan dan satu lagi yang merupakan REST API. Masing-masing adalah aplikasi yang berbeda yang bersedia untuk mengkonfigurasi secara berbeda. Itu dikalikan oleh beberapa lingkungan (produksi, pra-produksi, pengujian, pengembangan, dll.). Ini dengan mudah menghasilkan dalam 12 atau 15 konfigurasi dalam satu perusahaan.
Xavi Montero
@XaviMontero Saya mengikuti instruksi Anda PENDEKATAN KEDUA: dan ketika var_dump $ this-> contact_email atau tambahkan exit () pada fungsi setConfig () ia tidak keluar. Sepertinya setConfig tidak dipanggil
user742736
35

Saya harus menambahkan jawaban douglas, Anda dapat mengakses konfigurasi global, tetapi symfony menerjemahkan beberapa parameter, misalnya:

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

adalah

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

Anda dapat menggunakan var_dump untuk mencari kunci atau nilai yang ditentukan.

Felipe Buccioni
sumber
17

Untuk dapat mengekspos beberapa parameter konfigurasi untuk bundel Anda, Anda harus membaca dokumentasi untuk melakukannya. Ini cukup mudah dilakukan :)

Inilah tautannya: Cara mengekspos Konfigurasi Semantik untuk Bundel

Nikola Petkanski
sumber
Jujur, pertanyaan ini ditanyakan lebih dari 2 tahun yang lalu, saat itu, artikel di atas tidak ada.
josef.van.niekerk
10
Saya setuju dengan pernyataan itu. Saya telah mengatur jawabannya jika seseorang membuka artikel ini saat ini. Terima kasih atas penilaian negatifnya - Anda membuat hari saya menyenangkan.
Nikola Petkanski
Permintaan maaf saya, sekarang saya memikirkannya, downvote saya tidak pantas. Saya menghargai kontribusi Anda, saya mencoba untuk memperbaiki tetapi SO tidak mengizinkannya lagi. Tautan ini sangat membantu, dan saya yakin orang lain akan mendapat manfaat darinya! Mungkin admin dapat membantu mengubah downvote saya ???
josef.van.niekerk
Saya yakin Anda dapat mengklik lagi untuk membatalkan.
Nikola Petkanski
Anda tidak dapat membatalkan suara Anda lebih dari X (5?) Menit setelah Anda melakukannya atau sampai pesan diedit
cheesemacfly
3

Saya belajar cara mudah dari contoh kode http://tutorial.symblog.co.uk/

1) perhatikan ZendeskBlueFormBundle dan lokasi file

# myproject/app/config/config.yml

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

framework:

2) perhatikan Zendesk_BlueForm.emails.contact_email dan lokasi file

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

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

3) perhatikan bagaimana saya mendapatkannya di $ client dan lokasi file 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"));
    ...
    }
Kotoran
sumber