程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> YII 的源碼分析(三),yii源碼分析

YII 的源碼分析(三),yii源碼分析

編輯:關於PHP編程

YII 的源碼分析(三),yii源碼分析


前面已經看完了啟動一個yii程序所要經過的流程,以及渲染一個頁面是怎麼完成的。今天要分析的是yii是如何處理用戶請求的。也就是控制和動作部分。

還是以helloworld為例演示這一過程。我們在地址欄輸入http://localhost/study/yii/demos/helloworld/index.php,頁面就顯示了hello world.

前面的分析都是用的默認值,但是如果url有參數的時候,yii又是怎麼處理的呢?帶著這個問題,我們具體來分析一下。

在CWebApplication中有這樣一行代碼:

$route=$this->getUrlManager()->parseUrl($this->getRequest());

這就是傳說中的路由了,是不是有點小雞凍呢?先看看getUrlManager是個神馬。

    public function getUrlManager()
    {
        return $this->getComponent('urlManager');
    }

這個又要通過找關系了.

    public function getComponent($id,$createIfNull=true)
    {
        if(isset($this->_components[$id]))
            return $this->_components[$id];
        elseif(isset($this->_componentConfig[$id]) && $createIfNull)
        {
            $config=$this->_componentConfig[$id];
            if(!isset($config['enabled']) || $config['enabled'])
            {
                Yii::trace("Loading \"$id\" application component",'system.CModule');
                unset($config['enabled']);
                $component=Yii::createComponent($config);
                $component->init();
                return $this->_components[$id]=$component;
            }
        }
    }

執行了return $this->_components[$id]; id就是傳進去的urlManager,其實從這裡也還看不出什麼,直接找到urlManager這個類,看parseUrl:

    public function parseUrl($request)
    {
        if($this->getUrlFormat()===self::PATH_FORMAT)
        {
            $rawPathInfo=$request->getPathInfo();
            $pathInfo=$this->removeUrlSuffix($rawPathInfo,$this->urlSuffix);
            foreach($this->_rules as $i=>$rule)
            {
                if(is_array($rule))
                    $this->_rules[$i]=$rule=Yii::createComponent($rule);
                if(($r=$rule->parseUrl($this,$request,$pathInfo,$rawPathInfo))!==false)
                    return isset($_GET[$this->routeVar]) ? $_GET[$this->routeVar] : $r;
            }
            if($this->useStrictParsing)
                throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
                    array('{route}'=>$pathInfo)));
            else
                return $pathInfo;
        }
        elseif(isset($_GET[$this->routeVar]))
            return $_GET[$this->routeVar];
        elseif(isset($_POST[$this->routeVar]))
            return $_POST[$this->routeVar];
        else
            return '';
    }

從上面的代碼來看,如果我們不在url上傳點東西,直接就return ''了。於是問題來了,參數要怎麼傳呢?

isset($_GET[$this->routeVar]) 

public $routeVar='r';

於是有辦法了,讓我們一起來使點壞吧。加上這樣的一個參數helloworld/index.php?r=abc

發現報錯了。說明abc這個控制器是不存在的,事實上也是不存在的,使點小壞壞而已,正所謂男人不壞,女人不愛。

改成helloworld/index.php?r=site就可以顯示hello world了,這是什麼鬼原理呢?原因很簡單,因為定義了site控制器嘛。

class SiteController extends CController
{
    /**
     * Index action is the default action in a controller.
     */
    public function actionIndex()
    {
        echo 'Hello World';
    }
}

好吧,這個我沒有意見,但是actionIndex又是神麼鬼?在yii中,這稱為動作。它捕獲的是控制器後面的參數,如果我們輸?r=site/index就是index,動作是用“/"進行分隔的,為了驗正一下我說的不是騙女孩子的鬼話,我在site控制器裡加一個動作給你看一下:

class SiteController extends CController
{
    /**
     * Index action is the default action in a controller.
     */
    public function actionIndex()
    {
        echo 'Hello World';
    }

    public function actionView()
    {
        echo 'Hello View';
    }

}

訪問?r=site/view的時候,是不是看到輸出'Hello View'了呢?肯定是的,雖然我讀的書少,但是你騙不了我的,有圖有真相:

我一點兒也不喜歡用site這個名字,test才是我的最愛,於是我又建了一個test控制器來嘗試一下。

眼尖的一定看到怎麼寫了一個actions,這是什麼鬼?我也是剛試了才知道,它其實是另一種表示方式。

我記得在blog那個例子中有用過,用來顯示驗證碼:

    /**
     * Declares class-based actions.
     */
    public function actions()
    {
        return array(
            // captcha action renders the CAPTCHA image displayed on the contact page
            'captcha'=>array(
                'class'=>'CCaptchaAction',
                'backColor'=>0xFFFFFF,
            ),
            // page action renders "static" pages stored under 'protected/views/site/pages'
            // They can be accessed via: index.php?r=site/page&view=FileName
            'page'=>array(
                'class'=>'CViewAction',
            ),
        );
    }

我把它理解為集中聲明第三方業務的動作集合,因為本控制器內的動作,我覺得還是action+ID 的方式直接。

什麼鬼?你說我用的是index.php/site/captcha 而不是index.php?r=site/captcha .這又得從配置文件說起。

        'urlManager'=>array(
            'urlFormat'=>'path',
            'rules'=>array(
                'post/<id:\d+>/<title:.*?>'=>'post/view',
                'posts/<tag:.*?>'=>'post/index',
                '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
            ),
        ),

urlFormat 有path 和 get兩種,如果在main.php中沒有指定,那麼就是get方式,也就是index.php?r=site/captcha這種。如果指定了,即index.php/site/captcha這種

從字面上也很好理解,path就是像路徑的格式,get就是?這種形式。

關於路由和控制器部分的內容還有很多,但是本節就到這裡了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved