Одна из новых возможностей Laravel 3.1 — отслеживание события PHPConfig::loader
, а через него — управление процессом загрузки конфигурационных файлов. Нам потребуется совсем немного кода, чтобы использовать этот крючок («hook») для добавления поддержки настроек в формате .yaml с сохранением стандартной загрузки настроек в PHP.php
.
Установка YAML
Перед тем, как мы сможем использовать YAML нам нужен его парсер под PHP. Самый лучший и простой в использовании из знакомых мне находится в библиотеке Symfony. Мы можем установить этот компонент используя Composer — если у вас он ещё не установлен сделайте это, как описано в моей статье «Composer в Laravel».
Теперь когда у вас есть Composer отредактируйте файл composer.json в папке установки Laravel:
{ "require": { "php": ">=5.3.0", "symfony/yaml": "2.0.*" } }
Далее запустите установку этого компонента, либо, если он уже установлен — его обновление:
shcd /path/to/my/project php composer.phar install # либо: php composer.phar update
Теперь компонент YAML должен быть готов к работе.
Регистрация YAML
Перед тем, как мы можем использовать парсер YAML нам нужно зарегистрировать его в нашем IoC-контейнере. Сделаем это добавив этот код d application/start.php:
IoC::singleton('yaml_parser', function () {
return new \Symfony\Component\Yaml\Parser();
});
IoC::singleton('yaml_dumper', function () {
return new \Symfony\Component\Yaml\Dumper();
});
Мы только что зарегистрировали два класса YAML: Dumper и Parser в контейнере IoC — благодаря этому мы сможем получать экземпляр парсера в любом месте нашего кода одним простым вызовом:
$parser = IoC::resolve('yaml_parser');
Событие загрузки
Настало время установить обработчик для события PHPConfig::loader
, упомянутого в начале статьи. Нам нужно сделать так, чтобы вместо функции PHPLaravel\Config::file()
вызывалась наша собственная функция — PHPMyConfig::file()
. Это делается в файле application/start.php. Технчески мы могли бы полностью заменить процесс загрузки файла, но нам всего лишь нужно немного расширить его функциональность. Итак... вот наш код в start.php:
/*
|--------------------------------------------------------------------------
| Laravel Configuration Loader
|--------------------------------------------------------------------------
|
| The Laravel configuration loader is responsible for returning an array
| of configuration options for a given bundle and file. By default, we
| use the files provided with Laravel; however, you are free to use
| your own storage mechanism for configuration arrays.
|
*/
Laravel\Event::listen(Laravel\Config::loader, function ($bundle, $file) {
require_once path('app').'libraries'.DS.'myconfig.php';
return MyConfig::file($bundle, $file);
// return Laravel\Config::file($bundle, $file);
});
Вам может показаться странным наличие здесь require_once, однако автозагрузчик Laravel инициализируется позже в процессе запуска и если бы мы зарегистрировали автозагрузку для нашего myconfig.php, то регистрация бы произошла дважды, так как папка libraries тоже регистрируется.
MyConfig::file()
Это место, где мы расширяем, или, технически, перекрываем стандартный обработчик PHPLaravel\Config::file()
. Вот наш libraries/myconfig.php:
<?php
class MyConfig extends Laravel\Config {
// Загрузка настроек из конфигурационного файла.
public static function file($bundle, $file) {
$config = array();
// Набор путей для загрузки. Обычно массив настроек пакета загружется первым,
// затем загружаются настройки среды (environment), что даёт нам удобный
// механизм перекрытия настроек в зависимости от среды выполнения.
foreach (static::paths($bundle) as $directory) {
$semi_path = $directory.$file;
if ($directory !== '') {
// .php-файлы наиболее часто используются, поэтому проверяем их в первую очередь^
if (file_exists($path = $semi_path.EXT)) {
$config = array_merge($config, require $path);
}
// Теперь очередь .yaml:
else if (file_exists($path = "$semi_path.yml")) {
$parser = IoC::resolve('yaml_parser');
$contents = file_get_contents($path);
$config = array_merge($config, $parser->parse($contents));
}
}
}
return $config;
}
}
Послесловие
Итак, теперь мы моем помещать настройки в файлы .yaml и .php. Не требуется вносить изменений в вызовы PHPConfig::get()
— всё делается как обычно. А если вы немного постараетесь, то сможете добавить любые другие парсеры в наш блок if..else.