YII学习第二十四天,Theme、Language和Module
通常一个Yii的app目录结构如下:?
引用app?
----assets?
----images?
----css?
----protected?
--------commands?
--------components?
--------config?
--------controllers?
--------extensions?
--------models?
--------modules?
--------views?
----themes?
--------classic?
------------views?
----------------layout?
----------------system?
----------------site?
Theme是Yii系统支持的。当设置了Yii::app()->theme="xxxx"的时候,app根目录下的themes中的相应的theme就会起作用。比如设置Yii::app()->theme="classic",那么themes/classic/views就会替代protected/views作为视图资源存放的地方,除非视图文件不存在,才会启用protected/views下的视图文件。?
Yii内置了翻译器,可以使用Yii::t()来进行翻译,这个可以通过Yii::app()->language来控制目标语言。?
Module是一个模块,包含了controller、model、view。?
在原生的Yii系统里是支持Theme和Module结合。比如系统里建立一个Module名字为test,在protected/modules下结构如下:?
protected?
----modules?
--------test?
------------components?
------------controllers?
------------models?
------------views?
----------------default?
----------------layouts?
------------TestModule.php?
这个时候设置了Yii::app()->theme="classic",就可以将protected/modules/test/views复制到themes/classic/views/下,并起名为test。?
但是如果要再结合language做i18n支持,就不是那么容易了。首先将i18n相关语言使用Yii::t()来翻译,本身是一个效率低下的事情;其次,因为语言不同,势必会影响到界面排版,所以用一个view文件来控制就显得捉襟见肘。?
解决的思路是在controller解析view文件路径的时候,加上language标识。优先级是先找themes下带language的路经,如果没有则找themes下不带language的路径,如果没有则找modules下的views的带language的路径,如果没有则找modules下的views的不带language的路径。?
我的做法如下:?
1、修改CController.php?
public function resolveViewFile($viewName,$viewPath,$basePath,$moduleViewPath=null){if(empty($viewName))return false;if($moduleViewPath===null)$moduleViewPath=$basePath;if(($renderer=Yii::app()->getViewRenderer())!==null)$extension=$renderer->fileExtension;else$extension='.php';if($viewName[0]==='/'){if(strncmp($viewName,'//',2)===0)$viewFile=$basePath.$viewName;else$viewFile=$moduleViewPath.$viewName;}else if(strpos($viewName,'.'))$viewFile=Yii::getPathOfAlias($viewName);else {$viewFileBak = $viewFile=$viewPath.DIRECTORY_SEPARATOR.$viewName;if (isset(Yii::app()->language)) {$viewFile=$viewPath.DIRECTORY_SEPARATOR.Yii::app()->language.DIRECTORY_SEPARATOR.$viewName;} }if(is_file($viewFile.$extension))return Yii::app()->findLocalizedFile($viewFile.$extension);else if($extension!=='.php' && is_file($viewFile.'.php'))return Yii::app()->findLocalizedFile($viewFile.'.php');else {if (isset($viewFileBak)) {if(is_file($viewFileBak.$extension))return Yii::app()->findLocalizedFile($viewFileBak.$extension);else if($extension!=='.php' && is_file($viewFileBak.'.php'))return Yii::app()->findLocalizedFile($viewFileBak.'.php');}}return false;}?2、在protected/components里新增TLController.php?
/** * Abstract controller class for Theme&Language Controller.<br> * @author henry * */abstract class TLController extends CController {/** * @var array context menu items. This property will be assigned to {@link CMenu::items}. */public $menu=array();/** * @var array the breadcrumbs of the current page. The value of this property will * be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links} * for more details on how to specify this property. */public $breadcrumbs=array();public function init() {parent::init();if ($this->hasEventhandler('onControllerInit')) {$this->onControllerInit(new CEvent($this));}//$this->layout = '/layouts/'.Yii::app()->language.'/column1';}/** * Supported befaviors * @return array */public function behaviors() {return array_merge(parent::behaviors(), array('themeBehavior'=>array('class'=>'application.behaviors.ThemeBehavior',),'langBehavior'=>array('class'=>'application.behaviors.LangBehavior',),));}public function onControllerInit($event) {$this->raiseEvent('onControllerInit', $event);}}?3、在protected/behaviors增加2个Behavior:?
//ThemeBehavior.phpclass ThemeBehavior extends CBehavior {const COOKIE_KEY = '__theme';public function events() {return array_merge(parent::events(), array('onControllerInit'=>'controllerInit',));}public function controllerInit($event) {$v = Yii::app()->request->getParam(self::COOKIE_KEY);if (!isset($v)) {$v = Yii::app()->request->cookies[self::COOKIE_KEY];if (!isset($v)) {$v = Yii::app()->theme->name;} else {$v = $v->value;}}Yii::app()->theme = $v;Yii::app()->request->cookies[self::COOKIE_KEY] = new CHttpCookie(self::COOKIE_KEY, $v);}}?
//LangBehavior.phpclass LangBehavior extends CBehavior {const COOKIE_KEY = '__lang';private $_lang = '';public function events() {return array_merge(parent::events(), array('onControllerInit'=>'controllerInit',));}public function controllerInit($event) {$v = Yii::app()->request->getParam(self::COOKIE_KEY);if (!isset($v)) {$v = Yii::app()->request->cookies[self::COOKIE_KEY];if (!isset($v)) {$v = Yii::app()->language;} else {$v = $v->value;}}Yii::app()->language = $v;Yii::app()->request->cookies[self::COOKIE_KEY] = new CHttpCookie(self::COOKIE_KEY, $v);}}?