4 August 2011

Различные конфиги для режима production и режима отладки. Два в одном

Yii
Привет, уважаемые хабралюди.
Из собственного опыта вы, наверное, уже знаете, как важно свести к минимуму те изменения, которые привносит в код вашего приложения режим отладки. Если же вы сопровождаете довольно крупный и уже запущенный проект, то тем более понимаете важность быстрой отладки, при которой за собой не придеться подчищать все сделанные для удобства разработки изменения.
Исследовав возможности Yii, мой друг не нашел функционала, реализующего эту возможность, и задался целью это исправить. В данном топике мы узнаем о том, как быстро и неопасно для вашего приложения изменять конфиг (его рабочую версию) под нужды разработчика. Подробности — под катом.
Только что стало известно, что подобное есть в кукбуке Yii.

Проблема


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

Решение


А решение очень простое: нам не нужно создавать копию конфига, если мы можем воспользоваться наследованием, применив его к массиву, возвращаемому файлом конфига. Каждый экземпляр приложения, вызванный с локального компьютера, будет создаваться с локальной версией конфига, а екземпляр, созданный по запросу с удаленного компьютера будет запускаться с параметрами из рабочей версии.
Перейдем к примерам. Вот обновленный входной файл нашего приложения — index.php:
<?php

$yii=dirname(__FILE__).'/../yii/framework/yii.php';

if($_SERVER['REMOTE_ADDR']=='127.0.0.1') { 
    // если зашли локально, 
    defined('YII_DEBUG') or define('YII_DEBUG',true);
    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
    //то использовать локальную версию конфига
    $config=dirname(__FILE__).'/protected/config/develop.php';
} else { 
    // если обращение происходит к рабочей версии приложения
    $config=dirname(__FILE__).'/protected/config/main.php'; 
    
}

require_once($yii);
Yii::createWebApplication($config)->run();

Теперь рассмотрим упомянутый выше файл '/protected/config/develop.php'. Если вы внимательно посмотрите на его логику, то поймете, что никакого изобретения велосипеда тут нет, а вся идея очень проста и заключается в наследовании массивов:
<?php
//функция для наследования массива
//ниже мы передадим в нее массив, возвращаемый файлом рабочей версии конфига
function array_extends(array $array1, array $array2) {
    foreach($array2 as $key=>$value) {
        if(is_int($key))
            $array1[]=$value;
        else if(empty($array1[$key]) || !is_array($value))
            $array1[$key]=$value;
        else if(is_array($value))
            $array1[$key]=array_extends($array1[$key], $value);
    }
    return $array1;
}
//наследуем в нашей локальной версии рабочую версию конфига
//параметры, задынные ниже, будут применены для локального вызова приложения
//не заданные здесь параметры будут унаследованы от рабочей версии
return array_extends(include('main.php'), array(
    // перезапишется значение
    'name'=>'Local version', 
    'import'=>array(
        // добавится еще один путь в import
        'application.extensions.yiidebugtb.*' 
        'application.extensions.yiidebugtb.*
    ),
    'modules'=>array(
        // добавится модуль gii к остальным модулям? подключенным в главном конфиге
        'gii'=>array(
            'class'=>'system.gii.GiiModule',
            'password'=>'password',
            ...
        ),
    ),
    'components'=>array(
		'db'=>array(
                        // меняем connectionString для отладки на локальной машине
			'connectionString' => 'mysql:host=localhost;dbname=mycms', 
                        // изменяем логин для отладки базы данных на локальной машине.
			'username' => 'root',
                        // изменяем пароль для отладки базы данных на локальной машине.
			'password' => '', 
            // включаем профилирование запросов
            'enableProfiling'=>true, 
            /* 'tablePrefix' => 'tbl_', определять не нужно поскольку он определен в дочернем массиве */
		),
        'log'=>array(
            // подключаем еще два дебагера в файл для удобной разработки
            'routes'=>array( 
                array(
                    'class'=>'XWebDebugRouter',
                    ...
                ),
                array(
                    'class'=>'CWebLogRoute',
                    ...
                ),
            )
        ),
    ),
));

Я думаю все, кто сталкивался с Yii Framework, непременно имели дело и с файлом protected/config/main.php, но я все же поясню: этот файл возвращает массив параметров, которые в итоге применяются к запущенному экземпляру приложения. Для наглядности я предоставлю очень сокращенный пример кода из этого файла:
<?php
return array(
	'name'=>'Working Version',
    ...
	'import'=>array(
		'application.models.*',
		'application.components.*',
    ),
	'modules'=>array(
		// uncomment the following to enable the Gii tool
        'admin',
	),
    ...
	// application components
	'components'=>array(
		'db'=>array(
			'connectionString' => 'mysql:host=localhost;dbname=host_db',
			'emulatePrepare' => true,
			'username' => 'hosh_login',
			'password' => 'hosh_password',
			'charset' => 'utf8',
            'tablePrefix' => 'tbl_',
		),
		'log'=>array(
			'class'=>'CLogRouter',
			'routes'=>array(
				array(
					'class'=>'CFileLogRoute',
					'levels'=>'error, warning',
				),
			),
		),
	),
    ...
);

Как видите, идея действительно очень проста, но может быть очень полезной, особенно что касается тех проектов, которые уже запущены.

TheAlien подсказал что это решение уже реализовано ссылка

Спасибо за внимание.
Tags:yii frameworkphp
Hubs: Yii
+3
5.4k 15
Comments 21