yii基礎知識-

控制器 是 CController 或其子類的實例。它在當用戶請求時由應用建立。 當一個控制器運行時,它執行所請求的動做,動做一般會引入所必要的模型並渲染相應的視圖。 動做 的最簡形式,就是一個名字以 action 開頭的控制器類方法。php

控制器一般有一個默認的動做。當用戶的請求未指定要執行的動做時,默認動做將被執行。 默認狀況下,默認的動做名爲 index。它能夠經過設置 CController::defaultAction 修改。api

以下是一個控制器類所需的最簡代碼。因爲此控制器未定義任何動做,對它的請求將拋出一個異常。數組

class SiteController extends CController
{
}

1. 路由 

控制器和動做以 ID 識別。控制器 ID 是一種 'path/to/xyz' 的格式,對應相應的控制器類文件protected/controllers/path/to/XyzController.php, 其中的標誌 xyz 應被替換爲實際的名字 (例如 post對應 protected/controllers/PostController.php). 動做 ID 是除去 action 前綴的動做方法名。例如,若是一個控制器類含有一個名爲 actionEdit 的方法,則相應的動做 ID 爲 editapp

用戶以路由的形式請求特定的控制器和動做。路由是由控制器 ID 和動做 ID 鏈接起來的,二者以斜線分割。 例如,路由 post/edit 表明 PostController 及其 edit 動做。默認狀況下,URLhttp://hostname/index.php?r=post/edit 即請求此控制器和動做。yii

注意: 默認狀況下,路由是大小寫敏感的,從版本 1.0.1 開始,能夠經過設置應用配置中的CUrlManager::caseSensitive 爲 false 使路由對大小寫不敏感。當在大小寫不敏感模式中時, 要確保你遵循了相應的規則約定,即:包含控制器類文件的目錄名小寫,且 控制器映射 和 動做映射 中使用的鍵爲小寫。ide

從 1.0.3 版本開始,應用能夠含有 模塊(Module). 模塊中,控制器動做的路由格式爲moduleID/controllerID/actionID 。 更多詳情,請閱讀 模塊相關章節.post

2. 控制器實例化 

控制器實例在 CWebApplication 處理到來的請求時建立。指定了控制器 ID , 應用將使用以下規則肯定控制器的類以及類文件的位置。性能

  • 若是指定了 CWebApplication::catchAllRequest , 控制器將基於此屬性建立, 而用戶指定的控制器 ID 將被忽略。這一般用於將應用設置爲維護狀態並顯示一個靜態提示頁面。ui

  • 若是在 CWebApplication::controllerMap 中找到了 ID, 相應的控制器配置將被用於建立控制器實例。this

  • 若是 ID 爲 'path/to/xyz'的格式,控制器類的名字將判斷爲 XyzController, 相應的類文件則爲protected/controllers/path/to/XyzController.php。例如, 控制器 ID admin/user 將被解析爲控制器類 UserController,類文件是 protected/controllers/admin/UserController.php。 若是類文件不存在,將觸發一個 404 CHttpException 異常。

在使用了 模塊 (1.0.3 版後可用) 後,上述過程則稍有不一樣。 具體來講,應用將檢查此 ID 是否表明一個模塊中的控制器。若是是的話,模塊實例將被首先建立,而後建立模塊中的控制器實例。

3. 動做 

如前文所述,動做能夠被定義爲一個以 action 單詞做爲前綴命名的方法。而更高級的方式是定義一個動做類並讓控制器在收到請求時將其實例化。 這使得動做能夠被複用,提升了可複用度。

要定義一個新動做類,可用以下代碼:

class UpdateAction extends CAction
{
    public function run()
    {
        // place the action logic here
    }
}

爲了讓控制器注意到這個動做,咱們要用以下方式覆蓋控制器類的actions() 方法:

class PostController extends CController
{
    public function actions()
    {
        return array(
            'edit'=>'application.controllers.post.UpdateAction',
        );
    }
}

如上所示,咱們使用了路徑別名 application.controllers.post.UpdateAction 指定動做類文件爲protected/controllers/post/UpdateAction.php.

過編寫基於類的動做,咱們能夠將應用組織爲模塊的風格。例如, 以下目錄結構可用於組織控制器相關代碼:

protected/
    controllers/
        PostController.php
        UserController.php
        post/
            CreateAction.php
            ReadAction.php
            UpdateAction.php
        user/
            CreateAction.php
            ListAction.php
            ProfileAction.php
            UpdateAction.php

動做參數綁定

從版本 1.1.4 開始,Yii 提供了對自動動做參數綁定的支持。 就是說,控制器動做能夠定義命名的參數,參數的值將由 Yii 自動從 $_GET 填充。

爲了詳細說明此功能,假設咱們須要爲 PostController 寫一個 create 動做。此動做須要兩個參數:

  • category: 一個整數,表明帖子(post)要發表在的那個分類的ID。
  • language: 一個字符串,表明帖子所使用的語言代碼。

從 $_GET 中提取參數時,咱們能夠再也不下面這種無聊的代碼了:

class PostController extends CController
{
    public function actionCreate()
    {
        if(isset($_GET['category']))
            $category=(int)$_GET['category'];
        else
            throw new CHttpException(404,'invalid request');
 
        if(isset($_GET['language']))
            $language=$_GET['language'];
        else
            $language='en';
 
        // ... fun code starts here ...
    }
}

如今使用動做參數功能,咱們能夠更輕鬆的完成任務:

class PostController extends CController
{
    public function actionCreate($category, $language='en')
    {
        $category=(int)$category;
 
        // ... fun code starts here ...
    }
}

注意咱們在動做方法 actionCreate 中添加了兩個參數。 這些參數的名字必須和咱們想要從 $_GET 中提取的名字一致。 當用戶沒有在請求中指定 $language 參數時,這個參數會使用默認值 en 。 因爲 $category 沒有默認值,若是用戶沒有在 $_GET 中提供 category 參數, 將會自動拋出一個 CHttpException (錯誤代碼 400) 異常。 Starting from version 1.1.5, Yii also supports array type detection for action parameters. This is done by PHP type hinting using the syntax like the following:

class PostController extends CController
{
    public function actionCreate(array $categories)
    {
        // Yii will make sure $categories be an array
    }
}

That is, we add the keyword array in front of $categories in the method parameter declaration. By doing so, if $_GET['categories'] is a simple string, it will be converted into an array consisting of that string.

Note: If a parameter is declared without the array type hint, it means the parameter must be a scalar (i.e., not an array). In this case, passing in an array parameter via $_GET would cause an HTTP exception.

4. 過濾器 

過濾器是一段代碼,可被配置在控制器動做執行以前或以後執行。例如, 訪問控制過濾器將被執行以確保在執行請求的動做以前用戶已經過身份驗證;性能過濾器可用於測量控制器執行所用的時間。

一個動做能夠有多個過濾器。過濾器執行順序爲它們出如今過濾器列表中的順序。過濾器能夠阻止動做及後面其餘過濾器的執行

過濾器能夠定義爲一個控制器類的方法。方法名必須以 filter 開頭。例如,現有的 filterAccessControl 方法定義了一個名爲 accessControl 的過濾器。 過濾器方法必須爲以下結構:

public function filterAccessControl($filterChain)
{
    // 調用 $filterChain->run() 以繼續後續過濾器與動做的執行。
}

其中的 $filterChain (過濾器鏈)是一個 CFilterChain 的實例,表明與所請求動做相關的過濾器列表。在過濾器方法中, 咱們能夠調用 $filterChain->run() 以繼續執行後續過濾器和動做。

過濾器也能夠是一個 CFilter 或其子類的實例。以下代碼定義了一個新的過濾器類:

class PerformanceFilter extends CFilter
{
    protected function preFilter($filterChain)
    {
        // 動做被執行以前應用的邏輯
        return true; // 若是動做不該被執行,此處返回 false
    }
 
    protected function postFilter($filterChain)
    {
        // 動做執行以後應用的邏輯
    }
}

要對動做應用過濾器,咱們須要覆蓋 CController::filters() 方法。此方法應返回一個過濾器配置數組。例如:

class PostController extends CController
{
    ......
    public function filters()
    {
        return array(
            'postOnly + edit, create',
            array(
                'application.filters.PerformanceFilter - edit, create',
                'unit'=>'second',
            ),
        );
    }
}

上述代碼指定了兩個過濾器: postOnly 和 PerformanceFilter。 postOnly 過濾器是基於方法的(相應的過濾器方法已在 CController 中定義); 而 performanceFilter 過濾器是基於對象的。路徑別名application.filters.PerformanceFilter 指定過濾器類文件是protected/filters/PerformanceFilter。咱們使用一個數組配置 PerformanceFilter ,這樣它就可被用於初始化過濾器對象的屬性值。此處 PerformanceFilter 的 unit 屬性值將被初始爲 second

使用加減號,咱們可指定哪些動做應該或不該該應用過濾器。上述代碼中, postOnly 應只被應用於 edit 和create 動做,而 PerformanceFilter 應被應用於 除了 edit 和 create 以外的動做。 若是過濾器配置中沒有使用加減號,則此過濾器將被應用於全部動做。

相關文章
相關標籤/搜索