yii框架源碼分析之創(chuàng)建controller代碼
更新時(shí)間:2011年06月28日 19:26:11 作者:
我們可以看到有時(shí)會(huì)使用protected目錄下的controller,有時(shí)會(huì)使用module中controller,具體是如何處理的呢,請(qǐng)看如下的分析
使用yii框架的url路徑一般形如hostname/?r=xxxx/xxxx/xxxx&sdfs=dsfdsf
我們可以看到有時(shí)會(huì)使用protected目錄下的controller,有時(shí)會(huì)使用module中controller,具體是如何處理的呢,請(qǐng)看如下的分析:
以下代碼摘自yii框架核心代碼%Yiiroot%/framework/web/CWebApplication.php
=================================================================================================
//1.runController是執(zhí)行一個(gè)controller的方法,$route是$_GET['r']
public function runController($route)
{
//在這里調(diào)用createController先去創(chuàng)建一個(gè)controller實(shí)例,由此可見(jiàn)createController是選擇controller的關(guān)鍵
if(($ca=$this->createController($route))!==null)
{
list($controller,$actionID)=$ca;
$oldController=$this->_controller;
$this->_controller=$controller;
$controller->init();
$controller->run($actionID);
$this->_controller=$oldController;
}
else
throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
array('{route}'=>$route===''?$this->defaultController:$route)));
}
==================================================================================================
//2.接下來(lái)我們分析createController,假設(shè)我們?cè)L問(wèn)的route是site/contact
public function createController($route,$owner=null)
{
//首次進(jìn)入這個(gè)函數(shù),$owner參數(shù)為空
if($owner===null)
$owner=$this;
//如果$route參數(shù)中不含/,那么使用默認(rèn)的controller
if(($route=trim($route,'/'))==='')
$route=$owner->defaultController;
$caseSensitive=$this->getUrlManager()->caseSensitive;
//為了能夠完整運(yùn)行下面的循環(huán),給$route后面加一個(gè)/
$route.='/';
//將/的位置保存在$pos中
while(($pos=strpos($route,'/'))!==false)
{
//$id是前半部分,即site
$id=substr($route,0,$pos);
if(!preg_match('/^\w+$/',$id))
return null;
if(!$caseSensitive)
$id=strtolower($id);
//$route變成后半部分,即contact
$route=(string)substr($route,$pos+1);
//controller根目錄或子目錄前綴
if(!isset($basePath)) // first segment
{
//首次進(jìn)入,$owner為空,沒(méi)有這個(gè)成員變量
//非首次進(jìn)入或$owner有值,有可能設(shè)置了這個(gè)成員變量,參見(jiàn)CWebModule類
if(isset($owner->controllerMap[$id]))
{
return array(
Yii::createComponent($owner->controllerMap[$id],$id,$owner===$this?null:$owner),
$this->parseActionParams($route),
);
}
//如果能通過(guò)getModule方法獲取到一個(gè)獨(dú)立模塊,則再次調(diào)用createController,適用于site是module名的情況,參考protected/config/main.php配置文件,例如你的controller在%webroot%/protected/module/site/controller/ContactController.php
if(($module=$owner->getModule($id))!==null)
return $this->createController($route,$module);
//controller的目錄:
//對(duì)于CWebApplication,對(duì)應(yīng)config['basePath'](參見(jiàn)配置文件)./controller/,例如你的controller在%webroot%/protected/controller/SiteController.php
//對(duì)于CModule的子類,對(duì)應(yīng)改子類所在文件夾./contoller/,例如你的controller在%webroot%/protected/module/site/controller/ContactController.php
$basePath=$owner->getControllerPath();
$controllerID='';
}
else
$controllerID.='/';
$className=ucfirst($id).'Controller';
$classFile=$basePath.DIRECTORY_SEPARATOR.$className.'.php';
//如果$classFile存在,根據(jù)上面所得到的controller類文件路徑,創(chuàng)建類實(shí)例
//如果不存在,則是子目錄下的controller,繼續(xù)循環(huán)尋找最終的controller,例如你的controller在%webroot%/protected/controller/somedir/SiteController
if(is_file($classFile))
{
if(!class_exists($className,false))
require($classFile);
if(class_exists($className,false) && is_subclass_of($className,'CController'))
{
$id[0]=strtolower($id[0]);
return array(
new $className($controllerID.$id,$owner===$this?null:$owner),
$this->parseActionParams($route),
);
}
return null;
}
$controllerID.=$id;
$basePath.=DIRECTORY_SEPARATOR.$id;
}
}
我們可以看到有時(shí)會(huì)使用protected目錄下的controller,有時(shí)會(huì)使用module中controller,具體是如何處理的呢,請(qǐng)看如下的分析:
以下代碼摘自yii框架核心代碼%Yiiroot%/framework/web/CWebApplication.php
復(fù)制代碼 代碼如下:
=================================================================================================
//1.runController是執(zhí)行一個(gè)controller的方法,$route是$_GET['r']
public function runController($route)
{
//在這里調(diào)用createController先去創(chuàng)建一個(gè)controller實(shí)例,由此可見(jiàn)createController是選擇controller的關(guān)鍵
if(($ca=$this->createController($route))!==null)
{
list($controller,$actionID)=$ca;
$oldController=$this->_controller;
$this->_controller=$controller;
$controller->init();
$controller->run($actionID);
$this->_controller=$oldController;
}
else
throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
array('{route}'=>$route===''?$this->defaultController:$route)));
}
==================================================================================================
//2.接下來(lái)我們分析createController,假設(shè)我們?cè)L問(wèn)的route是site/contact
public function createController($route,$owner=null)
{
//首次進(jìn)入這個(gè)函數(shù),$owner參數(shù)為空
if($owner===null)
$owner=$this;
//如果$route參數(shù)中不含/,那么使用默認(rèn)的controller
if(($route=trim($route,'/'))==='')
$route=$owner->defaultController;
$caseSensitive=$this->getUrlManager()->caseSensitive;
//為了能夠完整運(yùn)行下面的循環(huán),給$route后面加一個(gè)/
$route.='/';
//將/的位置保存在$pos中
while(($pos=strpos($route,'/'))!==false)
{
//$id是前半部分,即site
$id=substr($route,0,$pos);
if(!preg_match('/^\w+$/',$id))
return null;
if(!$caseSensitive)
$id=strtolower($id);
//$route變成后半部分,即contact
$route=(string)substr($route,$pos+1);
//controller根目錄或子目錄前綴
if(!isset($basePath)) // first segment
{
//首次進(jìn)入,$owner為空,沒(méi)有這個(gè)成員變量
//非首次進(jìn)入或$owner有值,有可能設(shè)置了這個(gè)成員變量,參見(jiàn)CWebModule類
if(isset($owner->controllerMap[$id]))
{
return array(
Yii::createComponent($owner->controllerMap[$id],$id,$owner===$this?null:$owner),
$this->parseActionParams($route),
);
}
//如果能通過(guò)getModule方法獲取到一個(gè)獨(dú)立模塊,則再次調(diào)用createController,適用于site是module名的情況,參考protected/config/main.php配置文件,例如你的controller在%webroot%/protected/module/site/controller/ContactController.php
if(($module=$owner->getModule($id))!==null)
return $this->createController($route,$module);
//controller的目錄:
//對(duì)于CWebApplication,對(duì)應(yīng)config['basePath'](參見(jiàn)配置文件)./controller/,例如你的controller在%webroot%/protected/controller/SiteController.php
//對(duì)于CModule的子類,對(duì)應(yīng)改子類所在文件夾./contoller/,例如你的controller在%webroot%/protected/module/site/controller/ContactController.php
$basePath=$owner->getControllerPath();
$controllerID='';
}
else
$controllerID.='/';
$className=ucfirst($id).'Controller';
$classFile=$basePath.DIRECTORY_SEPARATOR.$className.'.php';
//如果$classFile存在,根據(jù)上面所得到的controller類文件路徑,創(chuàng)建類實(shí)例
//如果不存在,則是子目錄下的controller,繼續(xù)循環(huán)尋找最終的controller,例如你的controller在%webroot%/protected/controller/somedir/SiteController
if(is_file($classFile))
{
if(!class_exists($className,false))
require($classFile);
if(class_exists($className,false) && is_subclass_of($className,'CController'))
{
$id[0]=strtolower($id[0]);
return array(
new $className($controllerID.$id,$owner===$this?null:$owner),
$this->parseActionParams($route),
);
}
return null;
}
$controllerID.=$id;
$basePath.=DIRECTORY_SEPARATOR.$id;
}
}
相關(guān)文章
PHP實(shí)現(xiàn)仿Google分頁(yè)效果的分頁(yè)函數(shù)
這篇文章主要介紹了PHP實(shí)現(xiàn)仿Google分頁(yè)效果的分頁(yè)函數(shù),實(shí)例分析了php實(shí)現(xiàn)分頁(yè)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
php數(shù)組函數(shù)序列之a(chǎn)rray_search()- 按元素值返回鍵名
array_search() 函數(shù)與 in_array() 一樣,在數(shù)組中查找一個(gè)鍵值。如果找到了該值,匹配元素的鍵名會(huì)被返回。如果沒(méi)找到,則返回 false2011-11-11
Laravel中擴(kuò)展Memcached緩存驅(qū)動(dòng)實(shí)現(xiàn)使用阿里云OCS緩存
這篇文章主要介紹了Laravel中擴(kuò)展Memcached緩存驅(qū)動(dòng)實(shí)現(xiàn)使用阿里云OCS緩存,本文擴(kuò)展了一個(gè)支持SASL 認(rèn)證模式的Memcached緩存驅(qū)動(dòng),需要的朋友可以參考下2015-02-02
php實(shí)現(xiàn)自定義中獎(jiǎng)項(xiàng)數(shù)和概率的抽獎(jiǎng)函數(shù)示例
這篇文章主要介紹了php實(shí)現(xiàn)自定義中獎(jiǎng)項(xiàng)數(shù)和概率的抽獎(jiǎng)函數(shù),涉及php字符串、數(shù)組的概率運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-05-05
php的sso單點(diǎn)登錄實(shí)現(xiàn)方法
這篇文章主要介紹了php的sso單點(diǎn)登錄實(shí)現(xiàn)方法,實(shí)例分析了sso單點(diǎn)登錄的原理與具體實(shí)施步驟,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01
解決laravel 出現(xiàn)ajax請(qǐng)求419(unknown status)的問(wèn)題
今天小編就為大家分享一篇解決laravel 出現(xiàn)ajax請(qǐng)求419(unknown status)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09
php實(shí)現(xiàn)解析xml并生成sql語(yǔ)句的方法
這篇文章主要介紹了php實(shí)現(xiàn)解析xml并生成sql語(yǔ)句的方法,涉及php針對(duì)xml格式文件的讀取、解析及sql字符串拼接相關(guān)操作技巧,需要的朋友可以參考下2018-02-02

