当前位置: 代码迷 >> .NET Framework >> Yii Framework组合Theme、Language和Module
  详细解决方案

Yii Framework组合Theme、Language和Module

热度:62   发布时间:2016-05-02 00:06:48.0
Yii Framework结合Theme、Language和Module
很长时间都在使用Yii做SNS游戏后台,其类导入、全局变量生命、对象自动实例化、Behavior、Event都十分好用。

最近研究了一下其WEB方面都东西,主要从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 [email protected] CMenu::items}.	 */	public $menu=array();	/**	 * @var array the breadcrumbs of the current page. The value of this property will	 * be assigned to [email protected] CBreadcrumbs::links}. Please refer to [email protected] 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);	}}
  相关解决方案