国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

YII 的源碼分析(-)

2019-11-15 01:58:09
字體:
來源:轉載
供稿:網友
YII 的源碼分析(-)

做為源碼分析的首秀,我就挑了yii(讀作歪依依而不是歪愛愛);它的贊美之詞我就不多說了,直接入正題。先準備材料,建議直從官網下載yii的源碼包(1.1.15)。

在demos里邊有一個最簡單的應用—helloworld.就是用yii框架輸出一句話:”hello world”;

我就從它下手,分析框架執行一個最小流程要經過哪些組件,淺析它的運行過程。

首先從單一入口文件開始閱讀。(源碼一般都是從調用處開始分析)

index.php 只有兩行代碼,非常的簡單,就是導入yiibase類 ,啟動應用。

// include Yii bootstrap filerequire_once(dirname(__FILE__).'/../../framework/yii.php');Yii::createWebapplication()->run();

//YiiBase is a helper class serving common framework functionalities.

//YiiBase是一個助手類,它服務于整個框架。YiiBase代碼有點長. 主要完成一些常量的定義和初始化。

代碼到這里似乎就終結了,頁面的內容也程現出來,可是框架到底做了些什么,我們卻一無所知。所以我們需要把這一步進行分解,把里邊的細節暴露出來。

Yii::createWebApplication()->run() 一共可以分成三部分

  1. Yii
  2. createWebApplication
  3. run

Yii 這個東西是什么? 這個很容易,從yii.php 可以找到這樣一行代碼class Yii extends YiiBase,說明它就是YiiBase的繼承類,而且作者的擴展是留空的,所以Yii就是YiiBase的一個引用而已。

眼下還有兩件事要搞清楚,一是這個new 做了什么操作,二是run做了什么操作?

先看第一個問題,new操作干了些什么事。

    public static function createWebApplication($config=null)    {        return self::createApplication('CWebApplication',$config);    }

它又把任務傳遞給了createApplication:

         public static function createApplication($class,$config=null)         {                   return new $class($config);         }

結合起來看,createWebApplication () 就是return new CWebApplication($config); 所以new 就是返回了CWebApplication的實例.然而這個CWebApplication類又在哪呢?它又是怎么引入的呢?它執行了哪些操作?帶著這些問題,我們再次回到YiiBase.php.

在YiiBase.php里邊定義了一個很長的數組,你可以找到:

'CWebApplication' => '/web/CWebApplication.php',

說膽CWebApplication這個類是屬于自動加載的。關于它是如何實現自動加載的,可以查看spl_autoload_register的相關文檔,在這里,我們先只要知道它是Yii框架給我們自動加載進來的就可以了。

我們繼續往CWebApplication這個里邊深挖。打開/web/CWebApplication.php這個文件,居然沒有構造函數,根據我的經驗,用了new的類,一般有一個構造函數進行一些初始化工作的,于是我試著往父類找找看。從 class CWebApplication extends CApplication 可以看出,父類是CApplication. 它確實有一個構造函數,代碼如下:

public function __construct($config=null)    {        Yii::setApplication($this);        // set basePath at early as possible to avoid trouble        if(is_string($config))            $config=require($config);        if(isset($config['basePath']))        {            $this->setBasePath($config['basePath']);            unset($config['basePath']);        }        else            $this->setBasePath('

這樣,new的過程就完結了,沒有什么特別的,下面我們重點來看看run做了哪些工作。在CWebApplication 找不到run方法,它來自父類CApplication:

  public function run()    {        if($this->hasEventHandler('onBeginRequest'))            $this->onBeginRequest(new CEvent($this));        register_shutdown_function(array($this,'end'),0,false);        $this->processRequest();        if($this->hasEventHandler('onEndRequest'))            $this->onEndRequest(new CEvent($this));    }

重點放在:$this->processRequest(); 因為前面和后面部分都是注冊事件相關的,當前條件下執行不到。而CApplication中的processRequest方法是抽象的,所以猜測是在子類中進行實現的。又回到CWebApplication中,查找processRequest:

    public function processRequest()    {        if(is_array($this->catchAllRequest) && isset($this->catchAllRequest[0]))        {            $route=$this->catchAllRequest[0];            foreach(array_splice($this->catchAllRequest,1) as $name=>$value)                $_GET[$name]=$value;        }        else            $route=$this->getUrlManager()->parseUrl($this->getRequest());        $this->runController($route);    }

注意重點在$this->runController($route);

    public function runController($route)    {        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)));    }

我們要注意的代碼只有兩行:

$controller->init();

$controller->run($actionID);

這里的$controller可以能過查看createController得知,就是默認的控制器Sitecontroller.php

而Action則是index,你問我是怎么看出來的?哈哈,我在猜不出來的地方echo或var_dump一下不就可以了嗎?這么簡單的邏輯,還輪不到xdebug 這樣的神器出場。后面我們分析路由的時候,會知道,沒有指明的時候,系統會有一個默認的index作為Action.

顯然,init什么也沒有做,看看run做了什么

Sitecontroller中沒有run方法,又要去它的父類中查找。從定義:class SiteController extends CController得出父類。

在CController中有這個方法:

    public function run($actionID)    {        if(($action=$this->createAction($actionID))!==null)        {            if(($parent=$this->getModule())===null)                $parent=Yii::app();            if($parent->beforeControllerAction($this,$action))            {                $this->runActionWithFilters($action,$this->filters());                $parent->afterControllerAction($this,$action);            }        }        else            $this->missingAction($actionID);    }

查看$this->createAction($actionID),得到return new CInlineAction($this,$actionID);

我們呆會再看這個CInlineAction,先看$this->runActionWithFilters($action,$this->filters());

public function runActionWithFilters($action,$filters)         {                   if(empty($filters)){                            $this->runAction($action);                   }                   else                   {                            $priorAction=$this->_action;                            $this->_action=$action;                            CFilterChain::create($this,$action,$filters)->run();                            $this->_action=$priorAction;                   }         }

顯然$filters是空的,所以執行第一個表達式$this->runAction($action);

public function runAction($action)         {                   $priorAction=$this->_action;                   $this->_action=$action;                   if($this->beforeAction($action))                   {                            if($action->runWithParams($this->getActionParams())===false){                                     $this->invalidActionParams($action);                            }                            else{                                     $this->afterAction($action);                            }                   }                   $this->_action=$priorAction;         }

這段代碼的重點是 $action->runWithParams($this->getActionParams())這一句;

這里的$action就是$this->createAction($actionID)返回的結果,而它的結果就是

return new CInlineAction($this,$actionID);

CInlineAction.php

是時候查看CInlineAction了;

 public function runWithParams($params)         {                   $methodName='action'.$this->getId();                   $controller=$this->getController();                   $method=new ReflectionMethod($controller, $methodName);                   if($method->getNumberOfParameters()>0)                            return $this->runWithParamsInternal($controller, $method, $params);                   else                            return $controller->$methodName();         }

哇哦,好高級,居然還用了反射,不過我喜歡!

不過呢,打印$method發現:

  1. object(ReflectionMethod)#6 (2

    發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    主站蜘蛛池模板: 广东省| 延寿县| 疏附县| 伊宁市| 沁水县| 芷江| 三河市| 泗洪县| 林甸县| 林周县| 民县| 韩城市| 灌云县| 邢台市| 咸丰县| 东光县| 云浮市| 安塞县| 咸宁市| 五华县| 县级市| 施甸县| 得荣县| 永春县| 阿鲁科尔沁旗| 武义县| 朝阳区| 泸西县| 章丘市| 洛扎县| 南安市| 红安县| 桂阳县| 阿合奇县| 海晏县| 承德市| 崇左市| 安达市| 巩留县| 宁武县| 平远县|

      • <source id="fj984"></source>
        <rp id="fj984"></rp>
          <source id="fj984"></source>