Подстановка значений в Zend_Config

    Когда в конфигурационном файле возникает необходимость использовать подстановку значений, официальная документация недвузначно намекает на применение, ИМХО, не самой удачной практики — использование констант в INI-файлах, например так:

    [production]
    includePaths.library = APPLICATION_PATH "/../library"
    bootstrap.path = APPLICATION_PATH "/Bootstrap.php"


    Я написал небольшой класс, который наследует и расширяет функциональность Zend_Config, позволяя использовать такой синтаксис:

    [production]
    path.application        = "${path.root}/application"
    path.configs            = "${path.application}/configs"
    includePaths.library    = "${path.root}/library"



    Вот пример его использования:
    // окружение определяется заранее
    $environment = 'production';

    // опредеялем путь к корню проекта
    $rootPath = dirname(__FILE__);

    // определяем путь к конфигу относительно корня проекта
    $configPath = rootPath . '/application/configs/application.ini';

    // загружаем "сырой" конфиг без подстановки значений
    // и с отключенным режимом read-only
    $configRaw = new Zend_Config_Ini($configPath, $environment, true);

    // присваиваем путь к корню проекта переменной конфига
    $configRaw->path->root = $rootPath;

    // выполняем подстановку значений, превращая "сырой" конфиг в "обработанный"
    $config = Inf_Config_Placeholder($configRaw);

    // далее используем конфиг, как обычно

    * This source code was highlighted with Source Code Highlighter.

    Одним из ограничений класса является отсутствие проверки на бесконечную рекурсию, вроде этой:
    [production]
    foo = "${bar}"
    bar = "${foo}"


    Пожалуйста, избегайте подобных конструкций, так как выполнение бесконечной рекурсии занимает 7 секунд даже на самых современных серверах.

    Код класса Inf_Config_Placeholder доступен на GitHub.

    P.S. Формат репозитория на GitHub'е - немного странный, потому что я не нашел более удачного формата для его использования в виде субмодуля в директории library своего проекта. Може, есть какие-то идеи?
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 15

      –2
      ммм одна неприятная особенность — нужно было разширять класс так чтобы он наследовал Zend_Config_Ini а не был дополнительным инструментом.
        0
        Я специально не наследовал Ini или Xml, чтобы подстановку можно было выполнять в любом типе конфигов.
          +1
          При чем тут Zend_Config_Ini?
          Ведь в данном случае нет зависимости от формата конфига. Можно юзать хоть ini, хоть xml, хоть array.

          2 автор: до кучи можно сделать парсинг плейсхолдеров по запросу секций, а не при инициализации конфига. Мелочь, а приятно.

            0
            С одной стороны — можно, а с другой — пока нагрузки низкие, погоды это не сделает, а когда нагрузки возрастут, то преобразованный конфиг просто целиком кладется в кэш.
            В данном случае я стараюсь придерживаться принципа KISS.
              0
              Ну я вообще имел ввиду избавление от этих 2 строк:

              // присваиваем путь к корню проекта переменной конфига
              $configRaw->path->root = $rootPath;

              // выполняем подстановку значений, превращая «сырой» конфиг в «обработанный»
              $config = Inf_Config_Placeholder($configRaw);

              они избыточны. Можно наследовать от фабрики zend_config и прямо там выполнять подстановку.
                0
                У Zend_Config нет фабрики.
                И я не ставил перед собой цель её написать :)
                Так что получилось то, что получилось.
                  0
                  Ну эти две строки в данном случае ни сколько не избыточны. Ведь «путь к корню проекта» как-то должен попасть в конфиг, для подстановки в плейсхолдеры. И тут выбран самый простой вариант: взять конфиг; добавить необходимые свойства; обгадить конфиг. KISS.

                  Другое дело, можно $rootPath сохранить в реестре(это значение много где может пригодится), и научить конфиг «общаться» с этим реестром. Но в вышеописанном варианте конфиг по сути сам будет является реестром(его частью? :)), который один раз инициализировался в бутстрапе и потом юзается.
                    0
                    Другое дело, можно $rootPath сохранить в реестре(это значение много где может пригодится), и научить конфиг «общаться» с этим реестром. Но в вышеописанном варианте конфиг по сути сам будет является реестром(его частью? :)), который один раз инициализировался в бутстрапе и потом юзается.

                    Ой-ой-ой, какие ужасные вещи вы говорите.
                    ИМХО, реестр — это антипаттерн, который компенсирует недостатки архитектуры проекта и поощряет добавление неявных связей между компонентами.

                    Если $rootPath понадобится каким-то другим компонентам системы, то пускай они и берут его из конфига :)
                    Ну, на самом деле, не напрямую из конфига, а экшн контроллер (например) будет конфигурировать эти «другие компоненты», получая конфиг из бутстрапа, который он, в свою очередь, получает через $this->getInvokeArg('bootstrap').
                    Как-то так.
                      0
                      На истинность никак не претендовал :)

                      Паттерны не панацея. Есть проекты, и есть решения… не обязательно одинаковые при этом.

                      з.ы. неужели Вы никогда не пользуетесь этим антипаттерном? ;)
                        0
                        Раньше пользовался.
                        Но даже тогда мне было стыдно и я никому не рассказывал о таких вещах :)
                        Сейчас позволяю себе только редкие поблажки в виде синглтонов :)
              0
              хм. а мне больше по душе xml, но это уже впрочем не по теме…
                0
                а мне, впрочем как и для самого PHP, наиболее по душе обычные массивы
                +3
                >>> выполнение бесконечной рекурсии занимает 7 секунд даже на самых современных серверах

                бесконечная рекурсия за 7 секунд возможна???
                  0
                  какая то конечная бесконечность получается :)
                    0
                    Заканчивается стек — заканчивается и рекурсия. Всё просто :)

                  Only users with full accounts can post comments. Log in, please.