Zend Framework — Объединение конфигов с поддержкой модулей
Одним из недостатков Zend Framework является то, что «автоматически» подгружается только один конфигурационный файл application.ini
. Однако иногда идеологически правильнее использовать несколько конфигов. Например, вынести всю конфигурацию для модуля в отдельный файл, находящийся в директории модуля. Или отделить конфигурацию базы данных от общего файла, что является наиболее правильным, особенно при разработке проектов командой разработчиков с использованием системы контроля версий (svn, cvs и т.п.). Во-первых не всем нужно знать пароли БД для production версии проекта, и у каждого могут быть свои параметры для работы с БД своей копии development версии. В этом случае логичнее отделить параметры базы данных от файла application.ini
, который у всех должен быть общим и записать их в файл, например, db.ini
, который у каждого будет индивидуальным и будет игнорироваться системой контроля версий.
Предложенный код будет автоматически подгружать конфиги ini
и xml
из директории configs всех директорий модулей. Для модуля по умолчанию файл application.ini
будет игнорироваться. Именование параметров для всех файлов кроме module.ini
и module.xml
аналогично файлу application.ini
.
Для файлов module.*
следует опускать modulename.
. То есть если в application.ini
для модуля admin
надо писать:
admin.resources.view.doctype = "HTML4_STRICT" admin.resources.view.title = "Администрирование" |
То в module.ini
надо писать
resources.view.doctype = "HTML4_STRICT" resources.view.title = "Администрирование" |
«admin
» добавится автоматически.
Файлы module.*
подгружаются после всех других конфигураций, соответственно при дублировании параметров перезаписывают соответствующее содержание.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | <?php /** * Config glue * Склеивает конфиги, расположенные в папке configs каждого модуля. * * @category RV * @package RV_Application * @subpackage Resource * @copyright Copyright (c) 2010 Roman V. Konovaltsev * @author Roman V. Konovaltsev * @version 1.0 */ /** * @see Zend_Application_Resource_ResourceAbstract */ require_once 'Zend/Application/Resource/ResourceAbstract.php'; class RV_Application_Resource_Configlue extends Zend_Application_Resource_ResourceAbstract { public function init() { $this->_mergeConfigs(); } protected function _mergeConfigs() { $front = Zend_Controller_Front::getInstance (); $modules = $front->getControllerDirectory(); // Приклеиваем все конфиги кроме конфигов модулей foreach (array_keys($modules) as $module) { $configPath = $front->getModuleDirectory($module) . DIRECTORY_SEPARATOR . 'configs'; if(is_dir($configPath)) { $cfgdir = new DirectoryIterator($configPath); $config = new Zend_Config($this->getBootstrap()->getOptions(), true); $modified = false; foreach ($cfgdir as $file) { $filePath = $file->getPathname(); if ($file->isFile() && is_file($filePath)) { $pi = pathinfo($filePath); $ext = strtolower($pi['extension']); if(($ext == 'ini' || $ext == 'xml') && !(($module == $front->getDefaultModule() && $pi['filename']=='application') || $pi['filename'] == 'module')) { $options = $this->_loadOptions($filePath); $config->merge($options); $modified = true; } } } if($modified) $this->getBootstrap()->setOptions($config->toArray()); } } // Приклеиваем конфиги модулей foreach (array_keys($modules) as $module) { $configPath = $front->getModuleDirectory($module) . DIRECTORY_SEPARATOR . 'configs'; if(is_dir($configPath)) { $appOptions = $this->getBootstrap()->getOptions(); $modified = false; if(is_file($configPath.DIRECTORY_SEPARATOR.'module.ini')) { $modified = true; $options = $this->_loadOptions($configPath.DIRECTORY_SEPARATOR.'module.ini'); if (array_key_exists($module, $appOptions)) { if (is_array($appOptions[$module])) $appOptions[$module] = array_merge($appOptions[$module], $options->toArray()); else $appOptions[$module] = $options->toArray(); } else $appOptions[$module] = $options->toArray(); } if(is_file($configPath.DIRECTORY_SEPARATOR.'module.xml')) { $modified = true; $options = $this->_loadOptions($configPath.DIRECTORY_SEPARATOR.'module.xml'); if (array_key_exists($module, $appOptions)) { if (is_array($appOptions[$module])) $appOptions[$module] = array_merge($appOptions[$module], $options->toArray()); else $appOptions[$module] = $options->toArray(); } else $appOptions[$module] = $options->toArray(); } if($modified) $this->getBootstrap()->setOptions($appOptions); } } } /** * Load the config file * * @param string $fullpath * @return array */ protected function _loadOptions($fullpath){ if (file_exists ( $fullpath )) { $pi = pathinfo($fullpath); switch (strtolower ( $pi['extension'] ) ) { case 'ini' : $cfg = new Zend_Config_Ini ( $fullpath, $this->getBootstrap ()->getEnvironment () ); break; case 'xml' : $cfg = new Zend_Config_Xml ( $fullpath, $this->getBootstrap ()->getEnvironment () ); break; default : throw new Zend_Config_Exception ( 'Invalid format for config file' ); break; } } else { throw new Zend_Application_Resource_Exception ( 'File does not exist' ); } return $cfg; } } |
Для работы данного кода необходимо положить данный файл по адресу
/path/to/your/project/library/RV/Application/Resource/Configlue.php
и прописать следующее в application.ini
:
pluginPaths.RV_Application_Resource = "RV/Application/Resource" resources.configlue = |
см. также
- Zend Framework — Модульная структуры проекта
- Zend Framework — Инициализация основных параметров view и layout для модуля
- Zend Framework — Пример организации модульной структуры проекта
Вы можете отслеживать комментарии к этой записи с помощью RSS 2.0. Вы можете оставить комментарий, или использовать trackback с вашего сайта.
У меня не работало. Когда в главном Bootstrap были функции инициализации.
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initView()
{
// some code
}
}
Текст ошибки
( ! ) Fatal error: Call to a member function doctype() on a non-object in D:\Middleware\OracleWT1\instances\instance1\config\OHS\ohs1\Konovaltsev\library\RV\Controller\Plugin\ModuleConfigLV.php on line 53
Поэтому не лишним будет указать что bootstrap.path = APPLICATION_PATH "/Bootstrap.php" должен быть следующего содежания
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
}
Будет интересно увидеть объяснение такого поведения от автора. Возможно бонально объявление initView() перетирает объект View и Zend просто игнорирует его. Заранее спасибо.
Не работал, видимо, сам конфиг
resources.view.doctype = "HTML4_STRICT"
а не склейка как таковая. Данный конфиг приведен просто для примера. Если где-то в коде что-то пытается дёрнуть из ресурсов объект view, а ему отдается ни разу не view (так как мы сами где-то что-то так написали) — ну, понятное дело, это не сработает :).
Подключил ваш ресурс для склейки, спасибо. Но router прописанные в modules/mod1/configs/module.ini не применяется. Отследил по коду, что в переменную $appOptions добавляется router под ключем mod1, затем вызывается
$this->getBootstrap()->setOptions($appOptions);
Подскажите, в чем суть
В application.ini я не вижу секции [production], от которой наследуются отсальные. Есть подозрение, что
; glue config from module
autoloaderNamespaces.Zendadd = «Zendadd_»
pluginPaths.Zendadd_Application_Resource = «Zendadd/Application/Resource»
resources.configlue =
просто не применяется. Если тут всё верно, то надо дебажить в вашем конкретном случае — во первых дергается ли Zendadd_Application_Resource_Configlue. Если дергается — насколько корректно склеиваются конфиги. Применяются ли они и не перезатираются ли чем-то потом…