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 以外的动做。 若是过滤器配置中没有使用加减号,则此过滤器将被应用于全部动做。

相关文章
相关标签/搜索