Zend Framework -> Zend_Config: работаем с настройками
Опубликовал FractalizeR на Ноябрь 8, 2007
Назначение и возможности
Класс Zend_Config предназначен для единообразной работы в ОО-стиле с конфигурационными файлами в трех (в 1.02) форматах: PHP Array (просто PHP файл с данными, представленными в виде массива PHP), INI-формата Windows и XML.
Zend_Config поддерживает древовидную структуру данных произвольной глубины. В формате PHP массивов и XML эта возможность поддерживается самим форматом, а в INI папки первого уровня – секции INI файла, а все последующие уровни обозначаются внедрением разделителя в имя опции внутри секций (об этом далее).
В формате PHP массивов поддерживаются все типы данных, которые вы только пожелаете сохранить в настройки, формат INI ограничен возможностями функции parse_ini_file, которая используется для парсинга (советую перед использованием конфигурационных файлов в этом формате внимательно прочитать документацию по этой функции и комментарии пользователей к ней. Есть достаточное количество дефолтов и ограничений), а из формата XML все данные возвращаются в текстовом виде.
При использовании форматов INI и XML есть возможность наследовать настройки одного раздела от другого.
Следует иметь ввиду, что as-is Zend_Config хоть и позволяет изменять значения внутри объекта конфигурации, но записывать измененный вариант он не может. Если такой функционал требуется, лучше обратиться к пакету Config из PEAR, который обладает куда большим количеством поддерживаемых форматов и возможностью конвертирования из одного формата в другой (и много-много всего другого!).
Требования
Нужно помнить, что сам фреймворк требует PHP минимум 5.1.4. Работа с настройками в формате PHP Array и INI будет поддерживаться без дополнительных расширений. Работа с XML требует наличия SimpleXML, который, впрочем, по умолчанию встроен в PHP5.
Внутреннее представление данных
Внутри объекта Zend Config все данные представляются в виде асоциативного массива (многомерного, если это необходимо). Из этого следует, что самым быстрым вариантом для работы будут либо формат PHPArray, либо INI файлы за счет того, что они преобразуются в массив одним вызовом parse_ini_file.
Формат исходных данных
PHP Array вариант 1 (внутри скрипта):
$configArray = array(
'webhost' => 'www.example.com',
'database' => array(
'adapter' => 'pdo_mysql',
'params' => array(
'host' => 'db.example.com',
'username' => 'dbuser',
'password' => 'secret',
'dbname' => 'mydatabase'
)
)
);
// Create the object-oriented wrapper upon the configuration data
require_once 'Zend/Config.php';
$config = new Zend_Config($configArray);
Поддержка этого формата находится в модуле Zend/Config.php. Дополнительно никаких модулей подключать не нужно
PHP Array вариант 2 (включение скрипта):
<?php
// config.php
return array(
'webhost' => 'www.example.com',
'database' => array(
'adapter' => 'pdo_mysql',
'params' => array(
'host' => 'db.example.com',
'username' => 'dbuser',
'password' => 'secret',
'dbname' => 'mydatabase'
)
)
);
<?php
// Configuration consumption
require_once 'Zend/Config.php';
$config = new Zend_Config(require 'config.php');
INI файл:
; Production site configuration data
[production]
webhost = www.example.com
database.type = pdo_mysql
database.host = db.example.com
database.username = dbuser
database.password = secret
database.name = dbname
; Staging site configuration data inherits from production and
; overrides values as necessary
[staging : production]
database.host = dev.example.com
database.username = devuser
database.password = devsecret
Наследование настроек определяется двоеточием после имени секции. Комментарии, как обычно, выделяются запятыми.
Поддержка этого формата находится в модуле Zend/Config/Ini.php. Дополнительно никаких модулей подключать не нужно
XML файл:
<?xml version="1.0"?>
<configdata>
<production>
<webhost>www.example.com</webhost>
<database>
<type>pdo_mysql</type>
<host>db.example.com</host>
<username>dbuser</username>
<password>secret</password>
<name>dbname</name>
</database>
</production>
<staging extends="production">
<database>
<host>dev.example.com</host>
<username>devuser</username>
<password>devsecret</password>
</database>
</staging>
</configdata>
Корневой элемент XML может называться произвольно. Его дочерние элементы определяют секции. Наследование настроек определяется атрибутом extends в теге секции. Разумеется, файл может иметь валидные XML комментарии.
Поддержка этого формата находится в модуле Zend/Config/Xml.php. Дополнительно никаких модулей подключать не нужно
Создание объекта
1. Если исходные данные представлены в виде PHP массива:
// Create the object-oriented wrapper upon the configuration data
require_once 'Zend/Config.php';
$config = new Zend_Config($configArray);
или так:
$config = new Zend_Config(require 'config.php');
2. Если исходные данные представлены в виде INI файла:
<?php
require_once 'Zend/Config/Ini.php';
$Settings['nestSeparator'] = ':';
$Configuration = new Zend_Config_Ini('/path/to/config.ini', 'sectionname', $Settings);
Первый параметр конструктора Zend_Config_Ini -путь к INI файлу, второй – имя секции для загрузки (можно передать null для загрузки всех секций. parse_ini_file в любом случае распарсит весь файл, Zend_Config_Ini просто отберет нужные значения). Третий параметр может быть либо ассоциативным массивом, либо булевым значением. В первом случае можно задать одну или обе опции: allowModifications - булево значение, разрешающее модифицировать значения, прочитанные из файла и nestSeparator - разделитель, используемый в именах параметров для имитации многоуровневой структуры. Во втором случае булево значение определяет значение опции allowModifications.
Наследование параметров указывается с помощью двоеточия в имени секции [sectiontwo: sectionone] будет означать, что вторая секция наследует все значения из первой.
3. Если исходные данные представлены в виде XML:
<?php
require_once 'Zend/Config/Xml.php';
$config = new Zend_Config_Xml('/path/to/config.xml', 'staging', true);
Первый параметр как обычно путь к конфигурационному файлу, второй – имя секции (null, если нужны все), а третий, необязательный – разрешение модификации загруженных значений.
Чтение значений
Значения получаются очень просто не зависимо от того, откуда читались настройки:
echo $config->database->host;
Если вам нужно получить какое-либо значение какого-либо ключа, а если его нет, какое-то определенное значение в качестве значения по умолчанию, воспользуйтесь такой формой:
$host = $config->database->get('host', 'localhost');
В этом случае первый параметр метода get определяет имя ключа, второй – значение по умолчанию, которое будет возвращено в случае его отсутствия.
Дополнительные операции
К объекту Zend_Config (и потомкам, таким как Zend_Config_Ini) могут быть применены операции count (будет возвращено количество разделов) и foreach.
foreach можно вкладывать друг в друга:
foreach($config as $settinglevel1) { foreach($setting1 as $settinglevel2) { ..... } }
При наследовании секций значения наследника замещают соответствующие значения родителя.
Объект Zend_Config (и наследники) имеют метод Merge, позволяющий подгрузить в объект содержимое другого объекта: $globalconfig->merge($localConfig);
Любой раздел может быть преобразован в массив вызовом toArray()
$MyVar = $config->database->params->toArray()
В этом случае в $MyVar окажется ассоциативный массив. Скажем, к базе данных с помощью Zend_Db можно подключаться так:
// Use the configuration data to connect to the database
$db = Zend_Db::factory($config->database->adapter,
$config->database->params->toArray());
Расширение классов
Для написания своего класса поддержки своего хранилища конфигурации достаточно унаследоваться от Zend_Config и перегрузить необходимые методы.
Заключение
Вот, пожалуй, и все, что можно рассказать про Zend_Config и товарищей. Не вижу особой необходимости в его использовании. Разве что для сохранения ОО стиля и красоты приложения. Во всяком случае, если я и буду его использовать, то скорее всего, именно для этого
Zend Framework -> Zend_Session - удобная ОО-работа с $_SESSION « Fractalizer’s Weblog сказал
[...] Комментарии (RSS) « Zend Framework -> Zend_Config: работаем с настройками [...]
san2999 сказал
если у вас есть свой класс, выполняющий подобный функционал, смысла может и нет.. А так хотя бы даже возможно работать с разными типа конфигов используя единый интерфейс. Я бы назвал класс приятной мелочью