侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

PHP的Yii框架中过滤器相关的使用总结

php  /  管理员 发布于 7年前   383

Yii过滤器简介

过滤器是一段代码,可被配置在控制器动作执行之前或之后执行。例如, 访问控制过滤器将被执行以确保在执行请求的动作之前用户已通过身份验证;性能过滤器可用于测量控制器执行所用的时间。

一个动作可以有多个过滤器。过滤器执行顺序为它们出现在过滤器列表中的顺序。过滤器可以阻止动作及后面其他过滤器的执行。

过滤器有两种写法:

  • 基于方法的过滤器
  • 基于自定义过滤器类的过滤器

无论哪种过滤器,都必须在控制器中重写控制器的public function filters()方法,设置哪个过滤器对哪个动作起作用。

基于方法的过滤器

编写基于方法的过滤器,要经过三步:

在控制器中编写动作(Action);
在控制器中编写过滤器函数,函数名必须以filter为前缀,如:function filterAccessControl();
重写父类CController的filters()方法,定义过滤器与动作的关系;
实例:

";         $filterChain->run();       }       /**       * 第三步:重写父类CController的filters()方法,定义过滤器与动作的关系       * @see CController::filters()       */       public function filters(){         return array(       //定义过滤器与动作的关联关系           'addFilter + add', //         array( // 'application.filters.TestFilter',           //         ),      );     }   } 

自定义过滤器类

自定义过滤器类,需要单独写一个过滤器类,并继承CFilter类,重写CFilter类下的部分方法。大家可以看一下CFilter类的代码,该类代码不多,还是很容易看懂的。

自定义过滤器实例:

TestFilter.preFilter.
"; return true; } /** * Performs the post-action filtering. * @param CFilterChain $filterChain the filter chain that the filter is on. */ protected function postFilter($filterChain) { echo "--->TestFilter.postFilter.
"; } }


在控制器中注册该自定义过滤器与动作的绑定关系:

/*** 第三步:重写父类CController的filters()方法,定义过滤器与动作的关系 * @see CController::filters() */ ublic function filters(){ return array(   //定义过滤器与动作的关联关系     'addFilter + add',       array(           'application.filters.TestFilter',     ),      ); 


我自定义了一个过滤器:TestFilter,继承了CFilter类,重写了CFilter类的两个主要方法:preFilter(前控制器,在动作执行前运行)和postFilter(后控制器,在动作执行后运行)。

两种控制器的执行顺序

假设我将上面编写的自定义过滤器类与动作actionAdd绑定,那么,自定义过滤器继承自父类CFilter两个方法:preFilter和postFilter,与绑定的actionAdd之间的执行顺序是怎样的呢?

经过试验,执行顺序为:CFilter::preFilter--------->UserController::actionAdd--------->CFilter::postFilter。

也就是说,在动作执行前后都可以执行过滤操作。

那么文章开头说“过滤器可以阻止动作及后面其他过滤器的执行”是怎么做到的呢?

看了CFilter::preFilter的官方注释就知道了:

@return boolean whether the filtering process should continue and the action should be executed。

CFilter::preFilter函数默认return
 true;即,默认执行后面的动作和后过滤器。如果在自定义过滤器类中,重写CFilter::preFilter方法,并return
 false;就可以阻止后面的动作和过滤器执行了!


使用过滤器

过滤器本质上是一类特殊的 行为,所以使用过滤器和 使用 行为一样。 可以在控制器类中覆盖它的 yii\base\Controller::behaviors() 方法来申明过滤器,如下所示:

public function behaviors(){  return [    [      'class' => 'yii\filters\HttpCache',      'only' => ['index', 'view'],      'lastModified' => function ($action, $params) {        $q = new \yii\db\Query();        return $q->from('user')->max('updated_at');      },    ],  ];}

控制器类的过滤器默认应用到该类的 所有 动作,你可以配置yii\base\ActionFilter::only属性明确指定控制器应用到哪些动作。 在上述例子中,HttpCache 过滤器只应用到index和view动作。 也可以配置yii\base\ActionFilter::except属性使一些动作不执行过滤器。

除了控制器外,可在 模块或应用主体 中申明过滤器。 申明之后,过滤器会应用到所属该模块或应用主体的 所有 控制器动作, 除非像上述一样配置过滤器的 yii\base\ActionFilter::only 和 yii\base\ActionFilter::except 属性。

补充: 在模块或应用主体中申明过滤器,在yii\base\ActionFilter::only 和 yii\base\ActionFilter::except 属性中使用路由 代替动作ID, 因为在模块或应用主体中只用动作ID并不能唯一指定到具体动作。.
当一个动作有多个过滤器时,根据以下规则先后执行:

预过滤

  • 按顺序执行应用主体中behaviors()列出的过滤器。
  • 按顺序执行模块中behaviors()列出的过滤器。
  • 按顺序执行控制器中behaviors()列出的过滤器。
  • 如果任意过滤器终止动作执行,后面的过滤器(包括预过滤和后过滤)不再执行。
  • 成功通过预过滤后执行动作。

后过滤

  • 倒序执行控制器中behaviors()列出的过滤器。
  • 倒序执行模块中behaviors()列出的过滤器。
  • 倒序执行应用主体中behaviors()列出的过滤器。

创建过滤器

继承 yii\base\ActionFilter 类并覆盖 yii\base\ActionFilter::beforeAction() 和/或 yii\base\ActionFilter::afterAction() 方法来创建动作的过滤器,前者在动作执行之前执行,后者在动作执行之后执行。 yii\base\ActionFilter::beforeAction() 返回值决定动作是否应该执行, 如果为false,之后的过滤器和动作不会继续执行。

下面的例子申明一个记录动作执行时间日志的过滤器。

namespace app\components;use Yii;use yii\base\ActionFilter;class ActionTimeFilter extends ActionFilter{  private $_startTime;  public function beforeAction($action)  {    $this->_startTime = microtime(true);    return parent::beforeAction($action);  }  public function afterAction($action, $result)  {    $time = microtime(true) - $this->_startTime;    Yii::trace("Action '{$action->uniqueId}' spent $time second.");    return parent::afterAction($action, $result);  }}


核心过滤器

Yii提供了一组常用过滤器,在yii\filters命名空间下,接下来我们简要介绍这些过滤器。

1.yii\filters\AccessControl

AccessControl提供基于yii\filters\AccessControl::rules规则的访问控制。 特别是在动作执行之前,访问控制会检测所有规则并找到第一个符合上下文的变量(比如用户IP地址、登录状态等等)的规则, 来决定允许还是拒绝请求动作的执行,如果没有规则符合,访问就会被拒绝。

如下示例表示表示允许已认证用户访问create 和 update 动作,拒绝其他用户访问这两个动作。

use yii\filters\AccessControl;public function behaviors(){  return [    'access' => [      'class' => AccessControl::className(),      'only' => ['create', 'update'],      'rules' => [        // 允许认证用户        [          'allow' => true,          'roles' => ['@'],        ],        // 默认禁止其他用户      ],    ],  ];}


2.认证方法过滤器

认证方法过滤器通过HTTP Basic Auth或OAuth 2 来认证一个用户,认证方法过滤器类在 yii\filters\auth 命名空间下。

如下示例表示可使用yii\filters\auth\HttpBasicAuth来认证一个用户,它使用基于HTTP基础认证方法的令牌。 注意为了可运行,yii\web\User::identityClass 类必须 实现 yii\web\IdentityInterface::findIdentityByAccessToken()方法。

use yii\filters\auth\HttpBasicAuth;public function behaviors(){  return [    'basicAuth' => [      'class' => HttpBasicAuth::className(),    ],  ];}

认证方法过滤器通常在实现RESTful API中使用。

3.yii\filters\ContentNegotiator

ContentNegotiator支持响应内容格式处理和语言处理。 通过检查 GET 参数和 Accept HTTP头部来决定响应内容格式和语言。

如下示例,配置ContentNegotiator支持JSON和XML响应格式和英语(美国)和德语。

use yii\filters\ContentNegotiator;use yii\web\Response;public function behaviors(){  return [    [      'class' => ContentNegotiator::className(),      'formats' => [        'application/json' => Response::FORMAT_JSON,        'application/xml' => Response::FORMAT_XML,      ],      'languages' => [        'en-US',        'de',      ],    ],  ];}


在应用主体生命周期过程中检测响应格式和语言简单很多, 因此ContentNegotiator设计可被引导启动组件调用的过滤器。 如下例所示可以将它配置在应用主体配置。

use yii\filters\ContentNegotiator;use yii\web\Response;[  'bootstrap' => [    [      'class' => ContentNegotiator::className(),      'formats' => [        'application/json' => Response::FORMAT_JSON,        'application/xml' => Response::FORMAT_XML,      ],      'languages' => [        'en-US',        'de',      ],    ],  ],];


补充: 如果请求中没有检测到内容格式和语言,使用formats和languages第一个配置项。
4.yii\filters\HttpCache

HttpCache利用Last-Modified 和 Etag HTTP头实现客户端缓存。例如:

use yii\filters\HttpCache;public function behaviors(){  return [    [      'class' => HttpCache::className(),      'only' => ['index'],      'lastModified' => function ($action, $params) {        $q = new \yii\db\Query();        return $q->from('user')->max('updated_at');      },    ],  ];}


5.yii\filters\PageCache

PageCache实现服务器端整个页面的缓存。如下示例所示,PageCache应用在index动作, 缓存整个页面60秒或post表的记录数发生变化。它也会根据不同应用语言保存不同的页面版本。

use yii\filters\PageCache;use yii\caching\DbDependency;public function behaviors(){  return [    'pageCache' => [      'class' => PageCache::className(),      'only' => ['index'],      'duration' => 60,      'dependency' => [        'class' => DbDependency::className(),        'sql' => 'SELECT COUNT(*) FROM post',      ],      'variations' => [        \Yii::$app->language,      ]    ],  ];}


6.yii\filters\RateLimiter

RateLimiter 根据 漏桶算法 来实现速率限制。

7.yii\filters\VerbFilter

VerbFilter检查请求动作的HTTP请求方式是否允许执行,如果不允许,会抛出HTTP 405异常。 如下示例,VerbFilter指定CRUD动作所允许的请求方式。

use yii\filters\VerbFilter;public function behaviors(){  return [    'verbs' => [      'class' => VerbFilter::className(),      'actions' => [        'index' => ['get'],        'view'  => ['get'],        'create' => ['get', 'post'],        'update' => ['get', 'put', 'post'],        'delete' => ['post', 'delete'],      ],    ],  ];}


8.yii\filters\Cors

跨域资源共享 CORS 机制允许一个网页的许多资源(例如字体、JavaScript等) 这些资源可以通过其他域名访问获取。 特别是JavaScript's AJAX 调用可使用 XMLHttpRequest 机制,由于同源安全策略该跨域请求会被网页浏览器禁止. CORS定义浏览器和服务器交互时哪些跨域请求允许和禁止。

yii\filters\Cors 应在 授权 / 认证 过滤器之前定义,以保证CORS头部被发送。

use yii\filters\Cors;use yii\helpers\ArrayHelper;public function behaviors(){  return ArrayHelper::merge([    [      'class' => Cors::className(),    ],  ], parent::behaviors());}


Cors 可转为使用 cors 属性。

  • cors['Origin']: 定义允许来源的数组,可为['*'] (任何用户) 或 ['http://www.myserver.net', 'http://www.myotherserver.com']. 默认为 ['*'].
  • cors['Access-Control-Request-Method']: 允许动作数组如 ['GET', 'OPTIONS', 'HEAD']. 默认为 ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'].
  • cors['Access-Control-Request-Headers']: 允许请求头部数组,可为 ['*'] 所有类型头部 或 ['X-Request-With'] 指定类型头部. 默认为 ['*'].
  • cors['Access-Control-Allow-Credentials']: 定义当前请求是否使用证书,可为 true, false 或 null (不设置). 默认为null.
  • cors['Access-Control-Max-Age']: 定义请求的有效时间,默认为 86400.

例如,允许来源为 http://www.myserver.net 和方式为 GET, HEAD 和 OPTIONS 的CORS如下:

use yii\filters\Cors;use yii\helpers\ArrayHelper;public function behaviors(){  return ArrayHelper::merge([    [      'class' => Cors::className(),      'cors' => [        'Origin' => ['http://www.myserver.net'],        'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],      ],    ],  ], parent::behaviors());}


可以覆盖默认参数为每个动作调整CORS 头部。例如,为login动作增加Access-Control-Allow-Credentials参数如下所示:

use yii\filters\Cors;use yii\helpers\ArrayHelper;public function behaviors(){  return ArrayHelper::merge([    [      'class' => Cors::className(),      'cors' => [        'Origin' => ['http://www.myserver.net'],        'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],      ],      'actions' => [        'login' => [          'Access-Control-Allow-Credentials' => true,        ]      ]    ],  ], parent::behaviors());}

您可能感兴趣的文章:

  • 详解在PHP的Yii框架中使用行为Behaviors的方法
  • YII框架行为behaviors用法示例
  • YII2.0框架行为(Behavior)深入详解
  • Yii控制器中filter过滤器用法分析
  • Yii净化器CHtmlPurifier用法示例(过滤不良代码)
  • YII Framework的filter过滤器用法分析
  • 详解PHP的Yii框架中的Controller控制器
  • Yii2创建控制器(createController)方法详解
  • yii2控制器Controller Ajax操作示例
  • Yii2设置默认控制器的两种方法
  • yii2 在控制器中验证请求参数的使用方法
  • Yii2.0框架behaviors方法使用实例分析


  • 上一条:
    PHP的邮件群发系统phplist配置方法详细总结
    下一条:
    简介PHP的Yii框架中缓存的一些高级用法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(95个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客