Yii框架學習第二天-執行流程

我直的很懶,由於大概流程我已搞懂,我也懶得一步步分析了,轉載吧。

6、$config 之 import  

 
其中 import 被傳遞給 CModule 的 setImport:  
   1. public function setImport($aliases)  
   2. {  
   3.    foreach($aliases as $alias)  
   4.     Yii::import($alias);  
  5. }  

Yii::import($alias)裏的處理:  
   1. public static function import($alias,$forceInclude=false)  
   2. {  
   3.    // 先判斷$alias是否存在於YiiBase::$_imports[] 中,已存在的直接return, 避免重複import。  
   4.    if(isset(self::$_imports[$alias])) // previously imported  
   5.     return self::$_imports[$alias];  
   6.  
   7.    // $alias類已定義,記入$_imports[],直接返回  
   8.    if(class_exists($alias,false))  
   9.     return self::$_imports[$alias]=$alias;  
  10.  
  11.    // 類似 urlManager 這樣的已定義於$_coreClasses[]的類,或不含.的直接類名,記入$_imports[],直接返回  
  12.    if(isset(self::$_coreClasses[$alias]) || ($pos=strrpos($alias,'.'))===false// a simple class name  
  13.    {  
  14.     self::$_imports[$alias]=$alias;  
  15.     if($forceInclude)  
  16.     {  
  17.      if(isset(self::$_coreClasses[$alias])) // a core class  
  18.       require(YII_PATH.self::$_coreClasses[$alias]);  
  19.      else 
  20.       require($alias.'.php');  
  21.     }  
  22.     return $alias;  
  23.    }  
  24.  
  25.    // 產生一個變量 $className,爲$alias最後一個.後面的部分  
  26.    // 這樣的:'x.y.ClassNamer'  
  27.    // $className不等於 '*', 並且ClassNamer類已定義的,      ClassNamer' 記入 $_imports[],直接返回  
  28.    if(($className=(string)substr($alias,$pos+1))!=='*' && class_exists($className,false))  
  29.     return self::$_imports[$alias]=$className;  
  30. 
  31.    // 取得 $alias 裏真實的路徑部分並且路徑有效  
  32.    if(($path=self::getPathOfAlias($alias))!==false)  
  33.    {  
  34.     // $className!=='*',$className 記入 $_imports[]  
  35.     if($className!=='*')  
  36.     {  
  37.      self::$_imports[$alias]=$className;  
  38.      if($forceInclude)  
  39.       require($path.'.php');  
  40.      else 
  41.       self::$_classes[$className]=$path.'.php';  
  42.      return $className;  
  43.     }  
  44.     // $alias是'system.web.*'這樣的已*結尾的路徑,將路徑加到include_path中  
  45.     else // a directory  
  46.     {  
  47.      set_include_path(get_include_path().PATH_SEPARATOR.$path);  
  48.      return self::$_imports[$alias]=$path;  
  49.     }  
  50.    }  
  51.    else 
  52.     throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',  
  53.      array('{alias}'=>$alias)));  
  54. } 

   


7. $config 之 components  

   
$config 數組裏的 $components 被傳遞給CModule 的setComponents($components)  
   1. public function setComponents($components)  
   2. {  
   3.    foreach($components as $id=>$component)  
   4.    {  
   5.     if($component instanceof IApplicationComponent)  
   6.      $this->setComponent($id,$component);  
   7.     else if(isset($this->_componentConfig[$id]))  
   8.      $this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);  
  9.     else 
  10.      $this->_componentConfig[$id]=$component;  
  11.    }  
  12. }  
$componen是IApplicationComponen的實例的時候,直接賦值:  
$this->setComponent($id,$component),  
   1. public function setComponent($id,$component)  
   2. {  
   3.    $this->_components[$id]=$component;  
  4.    if(!$component->getIsInitialized())  
   5.     $component->init();  
   6. }  
如果$id已存在於_componentConfig[]中(前面註冊的coreComponent),將$component 屬性加進入。  
其他的component將component屬性存入_componentConfig[]中。  
 
   
8$config 之 params 
    
這個很簡單    
   1. public function setParams($value)  
   2. {  
   3.    $params=$this->getParams();  
   4.    foreach($value as $k=>$v)  
   5.     $params->add($k,$v);  
   6. }  
configure 完畢!  

   

9. attachBehaviors  

   

$this->attachBehaviors($this->behaviors);  
空的,沒動作  
預創建組件對象  
   1. $this->preloadComponents();  
   2.  
   3. protected function preloadComponents()  
   4. {  
   5.    foreach($this->preload as $id)  
   6.     $this->getComponent($id);  
   7. }  
getComponent() 判斷_components[] 數組裏是否有 $id的實例,如果沒有,就根據_componentConfig[$id]裏的配置來創建組件對象,調用組件的init()方法,然後存入_components[$id]中。  

10. init() 
 
this->init();  
函數內:$this->getRequest();  
創建了Reques 組件並初始化。  
   

11. run()  

   
   1. public function run()  
   2. {  
   3.    $this->onBeginRequest(new CEvent($this));  
   4.    $this->processRequest();  
   5.    $this->onEndRequest(new CEvent($this));  
   6. }  


三 大概過程  

application構造函數:  
1 設置當前運行實例  
2 獲取配置參數  
3 設置basepath  
4 設置幾個path;application,webroot ,ext  
5 preinit  
6 註冊error、exception處理函數 initSystemHandlers  
7 加載核心組件 registerCoreComponents 包括webapplication的和application的  
8 設置配置文件 configure($config)  
9 附加行爲 $this->attachBehaviors($this->behaviors);  
10處理加載config中的preload,//通過getComponent分別加載並初始化 $this->preloadComponents();   
11 初始化init(); //加載CHttpRequest組件 
 
run:  
1 處理onBeginRequest  
2 processRequest();真正處理請求  
3 處理onEndRequest  

webapplication->processRequest():  
1  如果配置文件設置了catchAllRequest , // 'catchAllRequest'=>array('site/error','p1'=>'1','p2'=>'2'),  
   則所有請求都跳轉到這個controller/action這個route,並且設置$_GET參數。        
2  分析url得到route,便於後面的控制器/動作創建     
3  執行runController 
       
runController:     
1 創建controller, createController(),創建失敗,則拋出404錯誤  
2 得到controller對象和actionID  
3 控制器初始化  $controller->init();  
4 最後執行   $controller->run($actionID);//真正執行頁面請求
  
控制器類  
CController:默認控制器在CWebApplication::defaultController定義('site'),可以在配置文件修改  
run():  
//根據actionID創建action對象,這裏生成的action對象分爲定義在controller內聯動作和自定義action,比如CViewAction  
  $action=$this->createAction($actionID),如果創建動作失敗,missingAction拋出404錯誤  
2 beforeControllerAction(beforeControllerAction定義在CWebApplication,有時也在module裏面)爲真,才執行runActionWithFilters;  
3 afterControllerAction    
runActionWithFilters($action,$this->filters()):  
//如果過濾器爲空,直接運行runAction()  
2 執行過濾器鏈  
runAction():  
1 beforeAction()返回真,才執行  
2 執行$action->runWithParams();注意:這裏存在多態,每個action都可以實現這個方法, 因爲CInlineAction自己實現了runWithParams()  
3 第2步驟爲真,才執行afterAction($action);  
動作類  默認動作在CController::$defaultAction定義('index'),可以在CController的繼承類重新定義  
runWithParams():  
1 分爲2種情況,1種是內聯動作,1種是通過控制器的actions方法定義的外聯動作。  
2 內聯動作 通過action+動作id作爲動作處理函數  
3 外聯動作 通過調用run()函數來實現  
4 如果動作方法參數個數大於0,執行runWithParamsInternal,否則直接執行動作方法。     
runWithParamsInternal();  
1 根據反射的方法對象得到方法的形參列表,從 控制器對象->getActionParams()得到實參,  
  如果實參有形參要求的參數,取其值,不然取形參默認值,否則,出錯。  
2 調用動作方法   2種形式 1是action+動作id ,2是Caction的派生類(比如cviewaction)的run()  
3 執行控制器的CController->render方法;$controller->render($view)  
控制器類  
CController:  
render();  
1 renderPartial();得到視圖,//先得到contact頁面的view文件內容,注意是用include的形式,所以其中的$this是指siteControlerd對象,  
  這裏調用了renderFile();  
2  然後$output=$this->renderFile($layoutFile,array('content'=>$output),true)  
   把view中的內容插入到佈局頁面layouts的column1.php,    'content'和layout的頁面的$content變量相關  
renderFile();  
1 如果程序沒有定義viewrender,則執行controller->renderInternal();否則,執行$renderer=Yii::app()->getViewRenderer())->renderFile(); 
view sourceprint?發生404錯誤  
errorHandler 在配置文件main中,'errorAction' => 'site/error',  

**********************************************************  

runActionWithFilters  
過濾:  
CFilterChain(繼承CList,提供數字索引存取功能,遍歷)::create($this,$action,$filters)->run();  
首先創建過濾鏈,然後執行過濾  
CFilterChain::create($controller,$action,$filters):  
$chain=new CFilterChain($controller,$action);創建一個過濾鏈$chain 
2 根據參數filters數組,遍歷創建過濾器$filter(字符串:通過CInlineFilter::create或者 數組:Yii::createComponent),  
  並且初始化$filter::init,通過$chain->add($filter)添加到過濾鏈中,並且返回這個過濾鏈$chain   
注意:如果是字符串,控制器類controller必須要有"filter"+過濾器名的方法。  
$chain::run();  
1 如果數字索引合法,得到$filter,然後執行$filter->filter($this);  
 1.1 $filter->filter($this):  
       1 執行動作的'filter'+過濾器名稱的方法。//比如CController::filterAccessControl($filterChain);  
   1.1.1 CController::filterAccessControl($filterChain):  
          1 $filter=new CAccessControlFilter;//新建過濾器  
          2 $filter->setRules($this->accessRules());//設置規則  
          3 $filter->filter($filterChain)  ;//執行過濾  
          4 $filter->preFilter($filterChain)爲真,繼續執行$filterChain->run();  
          5 $filter->postFilter($filterChain);//這個是在動作執行之後過濾  
2 否則,說明過濾完畢,$this->controller->runAction($this->action); 直接執行動作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章