Yii environment. Наследования и переопределение конфинов

от автора

Хочу рассказать вам про интересный опыт, с которым я столкнулся на своей последней работе. Нужна была гибкая система Environment-ов. После некоторого времени экспериментов я таки добился идеального варианта. Перейдем сразу к делу.

В protected я создал environment.php c такими вот 2я классами:

environment.php

class Environment { 	/** 	 * 	 */ 	const PRODUCTION = 10; 	/** 	 * 	 */ 	const STAGING = 20; 	/** 	 * 	 */ 	const TESTING = 30; 	/** 	 * 	 */ 	const DEVELOPMENT = 40;  	/** 	 * @var int 	 */ 	protected static $current;  	/** 	 * @var 	 */ 	private static $currentObj;  	/** 	 * 	 */ 	public static function instance() 	{ 		if(!self::$currentObj) 		{ 			self::$currentObj = new self(); 		} 		return self::$currentObj; 	}  	/** 	 * @param int $ENV 	 * @return bool 	 */ 	public function set($ENV = Environment::DEVELOPMENT) 	{ 		if(self::$current) 		{ 			return false; 		}  		if(isset($_GET['DEBUG'])) 		{ 			$this->setEnvironment($_GET['DEBUG']);  			$_SESSION['systemEnvironment'] = $_GET['DEBUG'];  		} 		elseif(isset($_SESSION['systemEnvironment']) and $_SESSION['systemEnvironment'] !== 'off') 		{ 			$this->setEnvironment($_SESSION['systemEnvironment']);  		} 		else 		{ 			self::$current = $ENV;  		} 		return true; 	}   	/** 	 * @return int 	 */ 	public static function getCurrent() 	{ 		return self::$current; 	}   	/** 	 * @param $level 	 */ 	private function setEnvironment($level) 	{ 		switch($level) 		{ 			case 'PRODUCTION': 				self::$current = self::PRODUCTION; 				break; 			case 'STAGING': 				self::$current = self::STAGING; 				break; 			case 'TESTING': 				self::$current = self::TESTING; 				break; 			case 'DEVELOPMENT': 				self::$current = self::DEVELOPMENT; 				break; 			case 'off': 				if(isset($_SERVER['ENVIRONMENT'])) 				{ 					self::$current = constant('Environment::' . strtoupper($_SERVER['ENVIRONMENT'])); 				} 				$_SESSION['systemEnvironment'] = null; 				break;  		} 	}  }   /**  * Class EnvironmentUtils  */ class EnvironmentUtils extends Environment { 	/** 	 * @param $rootDirectory 	 * @param $fileName 	 * @return string 	 */ 	public static function getConfigFile($rootDirectory, $fileName) 	{ 		$fileLink = $rootDirectory . '/config/'; 		switch(parent::$current) 		{ 			case Environment::DEVELOPMENT: 				$fileLink .= 'Development/'; 				break; 			case Environment::PRODUCTION: 				$fileLink .= 'Production/'; 				break; 			case Environment::STAGING: 				$fileLink .= 'Staging/'; 				break; 			case Environment::TESTING: 				$fileLink .= 'Testing/'; 				break;  		} 		return $fileLink . $fileName; 	} } 

После чего немного изменил структуру файлов в папке config:

Вот дерево файлов.

├── Base
│   ├── API
│   │   ├── Morpher.php
│   │   └── XmlRpcClient.php
│   ├── Common
│   │   ├── Daemon.php
│   │   ├── Email.php
│   │   └── Filtrator.php
│   ├── console.php
│   ├── DB
│   │   ├── 1c.php
│   │   └── BaseConnect.php
│   ├── main.php
│   ├── routes.php
├── Development
│   ├── cli.php
│   ├── DB
│   │   ├── 1c.php
│   │   ├── BaseConnect.php
│   └── Web.php
├── Production
│   ├── cli.php
│   ├── DB
│   │   ├── 1c.php
│   │   ├── BaseConnect.php
│   │   ├── Sape.php
│   └── Web.php
├── Staging
│   ├── cli.php
│   ├── DB
│   │   ├── 1c.php
│   │   ├── BaseConnect.php
│   └── Web.php
└── Testing
├── cli.php
├── DB
│   ├── 1c.php
│   └── BaseConnect.php
└── Web.php

В Base/Web.php находится базовый конфиг. Из серии:

return [ 	'basePath'          => PROTECTED_PATH, 	'name'              => 'MyApp', 	'theme'             => 'classic', 	'language'          => 'ru', 	'defaultController' => 'user/login', 	// preloading 'log' component 	// autoloading model and component classes 	'aliases'           => [ 		'bootstrap' => PROTECTED_PATH.'extensions/bootstrap', 		// change this if necessary 	], 	'preload'           => [ 		'log', 		'bootstrap' 	], 	'import'            => [ 		'application.models.*',         ] 

Тоже самое в cli.php. А вот в Production/Web.php чтоб не копировать постоянно какой то параметр если меняешь, я сделал так:

return CMap::mergeArray(include(PROTECTED_PATH.'config/Base/main.php'), 	[ 		'components'=> 		[ 			'db'         => include(dirname(__FILE__) . '/DB/BaseConnect.php'), 			'db1c'       => include(dirname(__FILE__) . '/DB/1c.php') 		] 	] ); 

Таким образом я просто перезаписываю настройки бд, ну или то, что мне нужно. Теперь самое интересное. Подгрузка. index.php.

P.S.: У меня в проекте ядро yii тянется через composer:

index.php

define("PROTECTED_PATH",realpath(dirname(__FILE__)).'/protected/'); if(!file_exists(PROTECTED_PATH.'vendor/autoload.php')) { 	die('autoload.php not found. Composer update!'); }  require_once(PROTECTED_PATH.'vendor/autoload.php'); require_once(PROTECTED_PATH.'environment.php');  if(isset($_SERVER['HTTP_ORIGIN'])) { 	if(in_array($_SERVER['HTTP_ORIGIN'],[....])) 	{ 	      header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']); 	      header('Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE, PUT'); 	      header('Access-Control-Max-Age: 1728000'); 	      header('Access-Control-Allow-Credentials: true'); 	      header("Access-Control-Allow-Headers: access-token, expiry, token-type, uid, client"); 	      header("Access-Control-Expose-Headers: access-token, expiry, token-type, uid, client"); 	}	 }   if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { 	header("HTTP/1.0 204 No Content"); 	die(); }  Environment::instance()->set(Environment::DEVELOPMENT);  switch(Environment::getCurrent()) { 	case Environment::DEVELOPMENT:  		define('YII_DEBUG', false); 		define('YII_SKIP_AUTH', true); 		define('YII_KERNEL_LOG', true); 		define('DISPLAY_ERROR_TRACE', true); 		define('YII_TRACE_LEVEL', 0); 		define('MINIFY_INTERFACE', false);  		error_reporting(E_ALL); 		ini_set('display_errors','On'); 		break; 	case Environment::PRODUCTION:  		define('YII_DEBUG', false); 		define('YII_SKIP_AUTH', false); 		define('YII_KERNEL_LOG', false); 		define('DISPLAY_ERROR_TRACE', false); 		define('YII_TRACE_LEVEL', 3); 		define('MINIFY_INTERFACE', true);  		error_reporting(0); 		ini_set('display_errors','Off'); 		break; 	case Environment::STAGING:  		define('YII_DEBUG', true); 		define('YII_SKIP_AUTH', false); 		define('YII_KERNEL_LOG', true); 		define('DISPLAY_ERROR_TRACE', true); 		define('YII_TRACE_LEVEL', 0);  		error_reporting(E_ALL); 		ini_set('display_errors','On'); 		break; }  /** @noinspection PhpUndefinedClassInspection */ Yii::$enableIncludePath = true; //For init Yii kernel $config = EnvironmentUtils::getConfigFile(PROTECTED_PATH,'Web.php');  //Other constants define('DATE_FORMAT', 'Y/m/d'); define('STATUS_NOACTIVE', 0); define('STATUS_ACTIVE', 1); date_default_timezone_set("Europe/Kiev");  /** @noinspection PhpUndefinedClassInspection */ Yii::createWebApplication($config)->run();  

По аналогии сделано и в cli.php. Система себя отлично зарекомендовала.

ссылка на оригинал статьи http://habrahabr.ru/post/264877/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *