首页 > 代码库 > Yii 丢失controller ID问题

Yii 丢失controller ID问题

用YII很久了今天看老代码发现了一个致命又气人的bug: “‘SiteController cannot find the requested view "index"

在这个项目里对应的views/site/index.php文件都有,但是为什么还报了这个错呢, 于是开始看内核代码:

	public function getViewFile($viewName)
	{
		if(($theme=Yii::app()->getTheme())!==null && ($viewFile=$theme->getViewFile($this,$viewName))!==false)
			return $viewFile;
		$moduleViewPath=$basePath=Yii::app()->getViewPath();
		if(($module=$this->getModule())!==null)
			$moduleViewPath=$module->getViewPath();
		return $this->resolveViewFile($viewName,$this->getViewPath(),$basePath,$moduleViewPath);
	}

结果发现 $this->getViewPath() 这句返回的是这样的东东“D:\www\Toplearning_PHP2\protected\views\” 没能看出问题继续往下看resolveViewFile方法

	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;
		}
		elseif(strpos($viewName,‘.‘))
			$viewFile=Yii::getPathOfAlias($viewName);
		else
			$viewFile=$viewPath.DIRECTORY_SEPARATOR.$viewName;

		if(is_file($viewFile.$extension))
			return Yii::app()->findLocalizedFile($viewFile.$extension);
		elseif($extension!==‘.php‘ && is_file($viewFile.‘.php‘))
			return Yii::app()->findLocalizedFile($viewFile.‘.php‘);
		else
			return false;
	}


记过发现$viewFile.$extension 返回的是“D:\www\Toplearning_PHP2\protected\views\\index” 这是个什么东东???? 本应该时这样地“...\views\controllerId\actionId”;  controllerId竟然丢了, 这也太不科学了, controllerId怎么可能会丢呢,于是到SiteController 打印了下$this 结果发现还真没有,这问题头大了, 于是乎从runController又看了一遍内核, 结果发现在"CController.php"这个文件里有个方法

	public function __construct($id,$module=null)
	{
		$this->_id=$id;
		$this->_module=$module;
		$this->attachBehaviors($this->behaviors());
	}

很明显在runController时Controller的ID是在这里初始化的,那好办了看看都谁认这个类当爹了,结果发现时protected/componets/Controller.php, 看看这个类吧

<?php
/**
 * Controller is the customized base controller class.
 * All controller classes for this application should extend from this base class.
 */
class Controller extends CController
{
	/**
	 * @var string the default layout for the controller view. Defaults to ‘column1‘,
	 * meaning using a single column layout. See ‘protected/views/layouts/column1.php‘.
	 */
 	public $layout=‘column1‘;
	/**
	 * @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 __construct()
	{
	    if (! isset($_COOKIE[‘SESSIONID‘]) && empty($_COOKIE[‘SESSIONID‘])) {
	        $_session_id = Yii::app()->getSession()->getSessionID();
	        setcookie("SESSIONID", $_session_id, time() + 3600);
	    } else {
	        $_session_id = $_COOKIE[‘SESSIONID‘];
	    }
	    session_id($_session_id);
	}

}

很明显这个类复写了父类的__construct方法结果没初始化父类的方法把ControllerId的初始化搞没了,改一下

public function __construct($id,$module=null)
	{
		parent::__construct($id,$module=null);
	    if (! isset($_COOKIE[‘SESSIONID‘]) && empty($_COOKIE[‘SESSIONID‘])) {
	        $_session_id = Yii::app()->getSession()->getSessionID();
	        setcookie("SESSIONID", $_session_id, time() + 3600);
	    } else {
	        $_session_id = $_COOKIE[‘SESSIONID‘];
	    }
	    session_id($_session_id);
	}