Как мне прочитать настройки конфигурации из 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
Пьер

4
Должен ли я внедрять контейнерный класс везде (контроллер, объект, класс), когда я использую этот оператор $ this-> container-> getParameter ('contact_email'); ? или есть более простой способ сделать это, не вводя контейнерный класс?
webblover

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

1
@webblover Просто вставьте сам параметр, используя %parameter_name%обозначение - (в YAML)
MauganRa

174

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

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

ПЕРВЫЙ ПОДХОД: Отдельный блок конфигурации, получение его в качестве параметра

С расширением ( подробнее о расширениях здесь ) вы можете легко «разделить» его на разные блоки в, config.ymlа затем ввести это как параметр, получаемый из контроллера.

Внутри вашего класса расширения внутри 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' );

ВТОРОЙ ПОДХОД: отдельный блок конфигурации, внедрение конфигурации в службу

Для читателей, которые ищут что-то подобное, но для получения конфигурации из службы, есть еще более приятный способ, который никогда не загромождает общее пространство "paramaters" и даже не требует containerпередачи в службу (передача всего контейнера - это практика для избегать).

Этот трюк выше по-прежнему "вводит" в пространство параметров вашего config.

Тем не менее, после загрузки определения службы вы можете добавить вызов метода, например, 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 и сорвите их»
eggmatters

Он имеет несколько приложений, особенно при развертывании параллельного автоматического тестирования, и особенно когда группа разрабатывает пакет, который в основном представляет собой модель или логику, которая используется несколькими другими командами в разных приложениях, например, приложение, которое является пользовательским интерфейсом, еще один является веб-интерфейсом панели администратора, а другой - REST API. Каждое из них представляет собой отдельное приложение, которое можно настраивать по-разному. Это умножается на несколько сред (производственная, предварительная, тестовая, разработка и т. Д.). Это позволяет легко реализовать 12 или 15 конфигураций в одной компании.
Хави Монтеро

@XaviMontero Я выполнил вашу инструкцию ВТОРОЙ ПОДХОД: и когда var_dump $ this-> contact_email или добавляет exit () в функцию setConfig (), он не выходит. Похоже, что setConfig не вызывается
user742736

36

Я должен добавить к ответу дугласа, вы можете получить доступ к глобальной конфигурации, но symfony переводит некоторые параметры, например:

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

находятся

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

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


Замечу, что параметры являются приватными в symfony 3+
Herz3h

17

Чтобы иметь возможность предоставлять некоторые параметры конфигурации для вашего пакета, вам следует обратиться к документации для этого. Сделать это довольно просто :)

Вот ссылка: Как предоставить семантическую конфигурацию для пакета


Честно говоря, этот вопрос был задан более 2-х лет назад, тогда статьи выше не существовало.
josef.van.niekerk

10
Я согласен с этим утверждением. Я дал ответ на тот случай, если кто-то откроет эту статью сейчас. Спасибо за отрицательную оценку - вы сделали мой день.
Никола Петкански

Мои извинения, теперь, когда я думаю об этом, мой голос против был необоснованным. Я ценю ваш вклад, я пытался проголосовать, но SO этого больше не позволяет. Ссылка очень полезна, и я уверен, что она принесет пользу другим людям! Может админ поможет мне изменить мой голос против ???
josef.van.niekerk

Я считаю, что вы можете нажать еще раз, чтобы отменить.
Никола Петкански

Вы не можете отменить свой голос более чем через X (5?) Минут после того, как вы это сделали, или пока сообщение не будет отредактировано
cheesemacfly


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.