Як прочитати налаштування конфігурації з Symfony2 config.yml?


191

Я додав налаштування до свого файла config.yml як такого:

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

За все життя я не можу зрозуміти, як її прочитати в змінну. Я спробував щось подібне в одному з моїх контролерів:

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

Але я отримую помилку:

Параметр "contact_email" повинен бути визначений.

Я очистив кеш, я також скрізь шукав документацію щодо перезавантаженого сайту Symfony2, але не можу дізнатися, як це зробити.

Напевно, просто занадто втомився, щоб зараз зрозуміти це. Хтось може допомогти у цьому?

Відповіді:


194

Замість того, щоб визначати contact_emailвсередині app.config, визначте це у parametersзаписі:

parameters:
    contact_email: somebody@gmail.com

Вам слід знайти дзвінок, який ви здійснюєте у своєму контролері.


4
Як би це працювало з середовищами Dev / Prod? Тож для тестування я хочу, щоб електронні листи були надіслані на тестовий лист, а виробництво отримало ще одне повідомлення електронної пошти
Філл Паффорд

2
@Phill: Якщо ви використовуєте стандартний swiftmailer у своєму symfony2, ви можете використовувати наступне налаштування у config_dev.yml: swiftmailer: delivery_address: dev@example.com Додаткову інформацію можна знайти в кулінарній книзі Symfony2
Pierre

4
Чи повинен я вводити клас контейнера скрізь (контролер, сутність, клас), коли я використовую цей вислів $ this-> container-> getParameter ('contact_email'); ? чи є більш простий спосіб зробити це без введення класу контейнерів?
webblover

1
Відповідно до цього рішення, як я можу отримати доступ до вкладених властивостей?
Усманія

1
@webblover Просто вставте сам параметр, використовуючи %parameter_name%нотацію - (у YAML)
MauganRa

173

Хоча рішення переміщення contact_emailдо параметра parameters.ymlє простим, як це пропонується в інших відповідях, це може легко захаращувати файл ваших параметрів, якщо ви маєте справу з багатьма пакетами або якщо ви маєте справу з вкладеними блоками конфігурації.

  • Спочатку я відповім строго на запитання.
  • Пізніше я наведу підхід для отримання цих конфігурацій із служб, не переходячи через загальний простір як параметри.

ПЕРШИЙ ПІДХІД: відокремлений блок конфігурацій, отримуючи його як параметр

За допомогою розширення ( докладніше про розширення тут ) ви можете зберігати це легко "розділеним" на різні блоки в, config.ymlа потім вводити це як параметр, отриманий від контролера.

Всередині класу Extension всередині DependencyInjectionкаталогу напишіть це:

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
    }

Потім у своєму config.yml, config_dev.yml і ви можете встановити

my_nice_project:
    contact_email: someone@example.com

Щоб мати можливість обробити це config.ymlвсередині вашого, MyNiceBundleExtensionвам також знадобиться Configurationклас у тому ж просторі імен:

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

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

        return $treeBuilder;
    }
}

Тоді ви можете отримати конфігурацію від свого контролера, як ви цього хотіли в своєму початковому запитанні, але зберігаючи parameters.ymlчистоту та встановивши її в config.ymlрозділах:

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

ДРУГИЙ ПІДХІД: Відокремлений блок конфігурацій, введення конфігурації в сервіс

Для читачів, які шукають щось подібне, але для отримання конфігурації з сервісу, є навіть приємніший спосіб, який ніколи не захаращує спільний простір "параметри" і навіть не потребує containerпередачі його в службу (передача всього контейнера - це практика уникати).

Цей фокус вище все ще "вводить" у простір параметрів вашого конфігурації.

Тим не менше, завантаживши своє визначення послуги, ви можете додати метод-виклик, наприклад, наприклад, setConfig()який вводить цей блок тільки в службу.

Наприклад, у класі 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' ] ) );
    }
}

Тоді services.ymlви визначаєте свою послугу як звичайну, без абсолютних змін:

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

А потім у своєму SillyManagerкласі просто додайте метод:

class SillyManager
{
    private $contact_email;

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

Зауважте, що це також працює для масивів замість скалярних значень! Уявіть, що ви налаштовуєте кролику із кроликами та потребуєте хоста, користувача та пароля:

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

Звичайно, вам потрібно змінити своє Дерево, але тоді ви можете зробити:

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

а потім у службі робіть:

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

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

Сподіваюся, це допомагає!


Якщо вам цікаво , що відрізняється від першого підходу і документації, це те , що значення конфігурації перетворюються в параметри в MyNiceProjectExtension->load()методі з цією лінією: $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ]);. Дякую Шаві!
jxmallett

Ідеальна відповідь, ганьба symfony не дозволяє вам отримати доступ до налаштування так само, як це робить параметри.
Мартін Лін

Це хороша відповідь, але це викриває тупий спосіб "конфігурування" програми Symfony. Який сенс мати довільні конфігураційні файли середовища, коли вам потрібно писати та викликати певні служби для доступу до них. Хіба хтось із Symfony не сидів там і не розумів: "Можливо, розробники дійсно хочуть надати для своїх програм специфічні для середовища значення, до яких вони можуть отримати доступ" Вид точки конфігураційних файлів, чи не так? Вони дотримуються схеми дизайну "STKTFANREO": "Встановіть ручки на F'd і відірвіть їх"
яєчники

У ньому є кілька застосувань, спеціально для розгортання паралельного автоматичного тестування, і, особливо, коли команда розробляє пакет, який в основному є модельним або логічним, який споживається кількома іншими командами в різних додатках, наприклад, програма, яка є переднім користувачем, ще один, який є веб-фронтом панелі адміністратора та інший, який є API REST. Кожен із них - це інша програма, яка бажає налаштовуватися на всі необхідні рівні. Це множиться на кілька середовищ (виробництво, передвиробництво, тестування, розробка тощо). Це легко дає 12 або 15 конфігурацій в одній компанії.
Хаві Монтеро

@XaviMontero Я дотримувався вашої інструкції ДРУГИЙ ПІДХОД: і коли var_dump $ this-> contact_email або додайте exit () у функції setConfig (), він не виходить. Схоже, setConfig не
дзвонить

35

Я маю додати до відповіді Douglas, ви можете отримати доступ до глобального конфігурації, але symfony перекладає деякі параметри, наприклад:

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

є

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

Ви можете використовувати var_dump для пошуку заданого ключа або значення.


17

Для того, щоб мати можливість виставити деякі параметри конфігурації для вашого пакета, вам слід ознайомитися з документацією для цього. Це зробити досить просто :)

Ось посилання: Як розкрити семантичну конфігурацію для пакета


Чесно кажучи, це запитання було задано більше 2 років тому, тоді, зазначеної статті не існувало.
josef.van.niekerk

10
Я згоден з цим твердженням. Я встановив відповідь на випадок, якщо хтось відкриє цю статтю сьогодні. Дякую за негативну оцінку - ти зробив мій день.
Микола Петканський

Мої вибачення, тепер, коли я думаю про це, мій потік не вимагався. Я ціную ваш внесок, я намагався проголосувати, але ТАК цього більше не дозволяє. Посилання є найбільш корисною, і я впевнений, що інші люди отримають користь від цього! Можливо, адміністратор може допомогти змінити мій внесок ???
josef.van.niekerk

Я вважаю, що ви можете натиснути ще раз, щоб скасувати.
Микола Петканський

Ви не можете скасувати свій голос більше X (5?) Хвилин після того, як ви зробили це або до того, як повідомлення буде відредаговано
cheesemacfly

7

Як це було сказано раніше - ви можете отримати доступ до будь-яких параметрів, використовуючи контейнер для ін'єкцій та використовувати його властивість параметрів.

"Symfony - робота з визначеннями служби контейнерів" - це хороша стаття про це.


3

Я дізнався простий шлях на прикладі коду http://tutorial.symblog.co.uk/

1) помітьте ZendeskBlueFormBundle та розташування файлів

# myproject/app/config/config.yml

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

framework:

2) зауважте Zendesk_BlueForm.emails.contact_email та розташування файлу

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

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

3) зауважте, як я отримую його в $ client та розташуванні файлів контролера

# 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"));
    ...
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.