Yii2 理解filters

    • 版本
    • ActionFilter
    • AccessControl
    • AccessRule
    • VerbFilter
    • 其它

1 版本

// yii\BaseYii\getVersion
public static function getVersion()
{
    return '2.0.10';
}

2 ActionFilter

动作过滤器的基类, 有两个重要的变量, 这两个变量都是存储action id

$except: 过滤器将不会应用于在这里面出现的action,即使出现在$only中,过滤器也不会有效。
$only: 如果为空, 该过滤器会应用于其owner下的所有过滤器。如果不为空, 则只应用于在这里面出现的action。

以上规则见代码:

protected function isActive($action)
{
    $id = $this->getActionId($action);
    // 如果为空, 过滤器判断为有效
    if (empty($this->only))
    {
        $onlyMatch = true;
    }
    else
    {
        // 判断action是否出现在$only中
        $onlyMatch = false;
        foreach ($this->only as $pattern)
        {
            if (fnmatch($pattern, $id))
            {
                $onlyMatch = true;
                break;
            }
        }
    }
    // --------- 拦路虎: 在这里面出现,即使前面判断过滤器有效, 也会变为无效
    $exceptMatch = false;
    foreach ($this->except as $pattern)
    {
        if (fnmatch($pattern, $id))
        {
            $exceptMatch = true;
            break;
        }
    }

    return !$exceptMatch && $onlyMatch;
}

3 AccessControl

该过滤器提供简单的访问控制

$user: 将会指向User,用于判断玩家的情况, 比如 $user->getIsGuest()判断玩家是否是游客。
$denyCallback: 如果没有通过过滤器, 将会指向denyCallback指向的回调函数, 如果没有设置,就会读取默认的denyAccess
protected function denyAccess($user)
{
    // 如果是游客, 则跳珠到登陆界面
    if ($user->getIsGuest())
    {
        // 如果没有定义登陆界面,则会报异常
        $user->loginRequired();
    }
    else
    {
        throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
    }
}
$ruleConfig: 默认的规则,指向yii\filters\AccessRule, 这个规则在后文讲述
$rules: 自定义的规则, 将会和$ruleConfig进行合并, 如果有相同项,会覆盖$ruleConfig
// 基类Object的构造函数中调用
public function init()
{
    parent::init();
    $this->user = Instance::ensure($this->user, User::className());
    foreach ($this->rules as $i => $rule)
    {
        if (is_array($rule))
        {
            // 如果没有更改$ruleConfig变量, 这里将rule配置一一生成AccessRule对象
            $this->rules[$i] = Yii::createObject(array_merge($this->ruleConfig, $rule));
        }
    }
}

客户端在请求的时候,会创建$controller, $action,然后执行$controller->runAction($action, …), 在runAction中,将会先执行过滤器的beforeAction,在这里也就是yii\filters\AccessController::beforeAction

具体流程见Yii2 分析Controller::behaviors 触发过程
http://blog.csdn.net/alex_my/article/details/54172619

public function beforeAction($action)
{
    $user = $this->user;
    $request = Yii::$app->getRequest();

    foreach ($this->rules as $rule)
    {
        // --------------- $rule->allows将在下文分析
        if ($allow = $rule->allows($action, $user, $request))
        {
            return true;
        }
        // --------------- 如果有定义denyCallback,则调用
        // --------------- 否则调用默认的denyAccess
        elseif ($allow === false)
        {
            if (isset($rule->denyCallback))
            {
                call_user_func($rule->denyCallback, $rule, $action);
            }
            elseif ($this->denyCallback !== null)
            {
                call_user_func($this->denyCallback, $rule, $action);
            }
            else
            {
                $this->denyAccess($user);
            }
            return false;
        }
    }
    if ($this->denyCallback !== null)
    {
        call_user_func($this->denyCallback, null, $action);
    }
    else
    {
        $this->denyAccess($user);
    }
    return false;
}

4 AccessRule

该类是AccessController的规则对象,其成员变量和AccessController中的rules合并,且相同键名的会被后者覆盖

$allow: 如果为true, 如果规则验证通过, 则表示该规则通过验证。如果为false,表示该规则一定不能通过。
$actions: 表示该规则应用于哪些action中, 如果为空, 则表示应用于所有的action中
$controllers: 表示该规则应用于哪些controller中,假设有BaseController::Controller做为自定义的控制器基类,在BaseController::behaviors可以设置规则只用于哪些派生类中:
public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'actions' => ['login', 'error', 'register', 'offline'],
                    'allow' => true,
                    'controllers' => [
                        'site'
                    ]
                ]
            ]
        ]
    ];
$roles: 指定该规则应用于哪些角色, 比如在rules中添加roles => ['Wang']
有两个特殊的角色:
?: 表示未登陆的游客
@: 表示已登陆的角色
$ips: 验证ip
$verbs: 指定该规则应用于哪些请求方法,比如GET, POST
$matchCallback: 通过调用自定义的函数来判断规则是否通过
$denyCallback: 表示验证未通过将会调用的函数

验证过程:

public function allows($action, $user, $request)
{
    if ($this->matchAction($action)
        && $this->matchRole($user)
        && $this->matchIP($request->getUserIP())
        && $this->matchVerb($request->getMethod())
        && $this->matchController($action->controller)
        && $this->matchCustom($action)
    )
    {
        return $this->allow ? true : false;
    }
    else
    {
        return null;
    }
}

5 VerbFilter

用于验证http请求的方法

public function behaviors()
{
    return [
        [
            'class' => VerbFilter::className(),
            // ---------- 指定action的访问规则
            'actions' => [
                'create' => ['get', 'post'],
                'delete' => ['post'],
                'upload'=>['post'],
                // 其它的都是用get
                '*' => ['get']
            ]
        ]
    ];
}

该过滤器将会执行EVENT_BEFORE_ACTION,在动作执行前进行判断, 验证未通过,则action不会继续执行下去。

6 其它

其余暂未使用到, 有用到再添加

时间: 2024-12-01 21:35:30

Yii2 理解filters的相关文章

Yii2 理解Component

版本 继承与实现 event和behaviors behaviors 添加Behavior到Component ensureBehaviors attachBehavior和attachBehaviors detachBehavior和detachBehaviors __get __set __call on和off 1 版本 // yii\BaseYii\getVersion public static function getVersion() { return '2.0.10'; } 2

Yii2 理解Validator

版本 Validator BooleanValidator CompareValidator DateValidator DefaultValueValidator EachValidator EmailValidator ExistValidator FileValidator FilterValidator ImageValidator IpValidator NumberValidator RangeValidator RegularExpressionValidator Required

Yii2 理解Controller

版本 继承与实现 actions createAction getModules runAction run findLayoutFile render renderContent 参考 1 版本 // yii\BaseYii\getVersion public static function getVersion() { return '2.0.10'; } 2 继承与实现 Controller继承与Component, 并实现了ViewContextInterface接口. 在Control

Yii2 理解di

链接 版本 简述 Container Instance TOP 示例说明 TOP 0 链接 http://alex-my.xyz/web/Yii2-理解di 1 版本 // yii\BaseYii\getVersion public static function getVersion() { return '2.0.10'; } 2 简述 简单的说就是di把类的构造函数分析好存储起来,配上给定的参数,创建实例. // 类名给定后通过php的反射机制获取构造函数信息 // set的第二个参数是构

Yii2 理解Object

版本 继承与实现 构造函数 __construct __get __set method_exists __isset __unset 其余判断函数 1 版本 // yii\BaseYii\getVersion public static function getVersion() { return '2.0.10'; } 2 继承与实现 Object实现了Configurable接口. Configureable要求在构造函数的参数末尾加上$config public function __c

深入理解Yii2.0乐观锁与悲观锁的原理与使用

本文介绍了深入理解Yii2.0乐观锁与悲观锁的原理与使用,分享给大家,具体如下: Web应用往往面临多用户环境,这种情况下的并发写入控制, 几乎成为每个开发人员都必须掌握的一项技能. 在并发环境下,有可能会出现脏读(Dirty Read).不可重复读(Unrepeatable Read). 幻读(Phantom Read).更新丢失(Lost update)等情况.具体的表现可以自行搜索. 为了应对这些问题,主流数据库都提供了锁机制,并引入了事务隔离级别的概念. 这里我们都不作解释了,拿这些关键

Yii2框架BootStrap样式的深入理解

Yii2框架默认采用了bootstrap作为CSS风格,各种视图类组件都如此.之前一直采用默认风格,并在必要的时候添加或者修改一下class来达到目的.但在改版Yii1.1的orange项目时,发现之前也是套的模板,其实没有好好去理解一下bootstrap的那套规则,所以顺便大致梳理一下吧.以basic模板为例,对照http://v3.bootcss.com/css/ 上的内容进行. 看layouts/main.PHP,Yii2默认以HTML5文档类型进行的了,但语言默认是en-US,所以要改,

Yii2 RESTful中api的使用及开发实例详解_php实例

什么是RESTful风格的API 对于各种客户端设备与服务端的通信,我们往往都通过API为客户端提供数据,提供某种资源.关于RESTful的概念,一查一大推,一两句也解释不清,姑且先按照我们通俗的理解:在众多风格.众多原则的API中,RESTful就是一套比较优秀的接口调用方式. Yii2如何实现RESTful风格的API 1.建立单独的应用程序 为了增加程序的可维护性,易操作性,我们选择新建一套应用程序,这也是为了和前台应用.后台应用区分开操作.有些人要嚷嚷了,为啥非得单独搞一套呢?如果你就单

Yii2使用驼峰命名的形式访问控制器的示例代码

yii2在使用的时候,访问控制器的时候,如果控制器的名称是驼峰命名法,那访问的url中要改成横线的形式.例如: public function actionRoomUpdate() { // } //访问的时候就要www.test.com/room-update这样访问 最近在做某渠道的直连的时候,他们提供的文档上明确指出接口的形式: 刚开始以为YII2中肯定有这样的设置,然后就去google了下,发现都说不行,自己去看了下,果然,框架里面直接是写死的:(源码)\vendor\yiisoft\y