Pull to refresh

Comments 21

Можно исходники привести в нормальный вид? А то я что-то потерялся тута :)
Кстати. Не знаю как вы, но даже однострочные ифы не перевериваю без скобок :)
Такой стиль кода у Yii и видимо автор его придерживается.
В ZF это делается простым наследованием секций к примеру в ini-файлах, очень удобно… Можно ведь, как вариант, использовать Zend_Config в Yii проектах.
Давайте подождем… Сейчас кто-нибудь рельсы вспомнить :) Хоть посмеемся…
Чьорт. Теги sarcasm съелись :) Но суть думаю понятна :)
а в симфони можно вообще сколько угодно энвайрментов создавать, из коробки три идут — прод, дев, тест. И конфиги там куда приятнее выглядят.
У меня немного другое решение, к тому же оно более расширенное :)

<?php
// Config base dir
$base = dirname(__FILE__).DIRECTORY_SEPARATOR.'protected'.DIRECTORY_SEPARATOR.
    'config'.DIRECTORY_SEPARATOR;

// Get the domain
$domain = $_SERVER['SERVER_NAME'];
if (strpos($domain, 'www.') !== false) {
	$domain = str_replace('www.', '', $domain);
}

if (!file_exists($base.'sites'.DIRECTORY_SEPARATOR.$domain.'.php')) {
	$domain = 'dev.example.com';
}

$main = include($base.'main.php');
$domain_config = include($base.DIRECTORY_SEPARATOR.'sites'.DIRECTORY_SEPARATOR.$domain.'.php');

// Load the Yii framework
$yii=dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'yii'
    .DIRECTORY_SEPARATOR.'framework'.DIRECTORY_SEPARATOR
    .(defined('YII_DEBUG') ? 'yii.php' : 'yiilite.php');
require_once($yii);

// Merge configs
$config = CMap::mergeArray($main, $domain_config);
// Init the application
/** @var $app CWebApplication */
$app = Yii::createWebApplication($config);
unset($domain, $base, $yii, $config, $main, $domain_config);

Yii::import("ext.yiiext.components.zendAutoloader.EZendAutoloader", true);

// you are able to load custom code that is using Zend class naming convention
// with different prefix
EZendAutoloader::$prefixes = array('Zend', 'Custom');
Yii::registerAutoloader(array("EZendAutoloader", "loadClass"));

$app->run();


Конфиг main.php содержит в себе все основные настройки, а в подпапке sites лежат все дополнительные настройки, спечифичные для каждого конкретного домена — в простейшем варианте это local, dev и production. У меня 1 проект висит на 5 доменах, так что это ещё и удобный multi-domain вариант, когда каждому домену нужно различающиеся настройки.

Прелесть CMap::mergeArray в том, что он обходит всё рекурсивно и добавляет (если элемента нету) или перекрывает (если элемент есть) элементы первого массива элементами из второго массива. Т.е. это позволяет мне держатьвсе настройки в main.php и переопределить отдельные настройки уже в специфическом для домена в его конфиге. Примерно вот так:

main.php
<?php
return array(
	'basePath' => dirname(__FILE__) . DIRECTORY_SEPARATOR . '..',
	'defaultController' => 'site',
	'components' => array(
		'urlManager' => array(
			'urlFormat' => 'path',
			'showScriptName' => false,
			'urlSuffix'=> '.html',
			'rules' => array(
				'<lang:\w{2}>/<controller:\w+>/<id:\d+>' => '<controller>/view',
				'<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
				'<lang:\w{2}>/<controller:\w+>/<action:\w+>' => '<controller>/<action>',
				'<lang:\w{2}>/<controller:\w+>' => '<controller>/index',
			),
		),

		'db' => array(
			'class' => 'system.db.CDbConnection',
			'charset' => 'utf8',
			'schemaCachingDuration'=>3600,
			'emulatePrepare' => true,
		),
	),
	'params' => array(
		'mail' => array(
			'smtp_from' => 'example@example.com',
			'pass' => '12345',
			'ip' => '192.168.0.1',
			'port' => '25',
		),
	),
);


example.com.php — production site config
<?php
return array(
	'components' => array(
		'db' => array(
			'connectionString' => 'mysql:host=mysql_host;dbname=project_db',
			'username' => 'production',
			'password' => 'production password',
		),
	),
);


dev.example.com.php — dev config
<?php
defined('YII_DEBUG') or define('YII_DEBUG',true);
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
return array(
	'components' => array(
		'db' => array(
			'connectionString' => 'mysql:host=localhost;dbname=project_db',
			'username' => 'devuser',
			'password' => 'dev password',
			'enableProfiling' => true,
			'enableParamLogging' => true,
			'schemaCachingDuration' => 0,
		),
	),
	'params' => array(
		'mail' => array(
			'smtp_from' => 'test@example.com',
			'pass' => 'localtest',
			'ip' => 'localhost',
			'port' => '25',
		),
	),
);


Надеюсь общая концепция понятна :)
А вам не кажется что по количеству буков данное решение является хумусом?
Непростому проекту непростые конфиги. Когда у вас на одной кодовой базе крутится 8 сайтов (и скажу далеко не визитки), отличающихся друг от друга дизайном, работающие с двумя базами — одной общей и по cms базе на каждый сайт — это ещё очень простое и элегантное решение на мой вкус. К тому же я же не выкладывал в примеры конфиги целиком — там гораздо больше опций, которые переопределяются для каждого сайта.

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

Я всего лишь поделился своим решением. Использовать или нет — дело каждого лично. Не нравится — не пользуйтесь :)
> Когда у вас на одной кодовой базе крутится 8 сайтов

Лично для меня это уже фейл. :)
Вы же не знаете что и как, так что судить зарание явно не стоит.
А чем функция array_merge_recursive не угодила вместо самописной array_extends?
// конфиг в виде масива выглядит ужасно, ini или yml удобнее
Работа функции array_merge_recursive отличается от работы самописной функции array_extends, и она не подходила для данной задачи. Конфиг php не выглядит ужасно. Это обычный код. Зато в отличии от ini или yml в нем можно использовать php конструкции и объявлять переменные. Хотя в целом это дело вкуса как хранить настройки
В symfony в yaml файлах тоже можно использовать php-код :) Не исключаю, что и в ini.
У нас тоже стояла задача разделения конфигов в Yii, но мы её решили по-другому, — двумя ветками в git, серверной и девелоперской. После окончания работ в серверную ветку мержится девелоперская. Единожды разрешив конфликт мы больше с ним не сталкиваемся.
мы используем другой подход code.google.com/p/pha-yii-author/ — авторская конфигурация.
плюсы:
— каждый разработчик/инсталяция может имет собственный конфиг (со всеми штатными возможностями наследования)
— для подключения нет необходимости вносить изменения в код (index.php) — нужный конфиг подключается автоматически, стоит создать соответствующий пустой файл (соответствующая директория добавляется в игнор в системе контроля версий).
— поскольку конфиг у кажого свой разработчки может не бояться поломать общий файл, подключать в свем конфиге различные экспериментальные фичи
как ставить/подключать описано на форуме www.yiiframework.ru/forum/viewtopic.php?f=9&t=2479&p=15258
Идея хорошая, но зачем такие сложности? можно реализовать всё гораздо проще, без расширений.

В корне создаём файлик ".author" и в нем пишем ник автора.

В index.php добавляем:
$webRoot = dirname(__FILE__);
$author = null;
$authorFile = $webRoot . '/.author';
if (is_file($authorFile)) {
    $author = trim(file_get_contents($authorFile));
}


ну и дальше как в вашем примере:
if (!empty($author)) {
    $config = $webRoot . '/protected/config/' . $author . '.php';
    if (!file_exists($config)) {
        $config = $webRoot . '/protected/config/main.php';
    }
    defined('YII_DEBUG') or define('YII_DEBUG',true);
    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

} else {
    $config = $webRoot . '/protected/config/production.php';
}


Авторские конфиги и «prodaction» мержим с «main», как описано в «рецептах»:
<?php
return CMap::mergeArray(
    require(dirname(__FILE__) . '/main.php'),
    array(
        'components'=>array(
            'db' => array(
            ...
            ),
        ),
    )
); 
Sign up to leave a comment.

Articles

Change theme settings