创建一个自定义过滤器

过滤器是一种对象,它会在控制器动作之前或者之后运行。例如,一个访问控制过滤器可能会在动作之前运行,确保它们只能被特殊的终端用户访问;一个内容压缩过滤器可能会在动作之后运行,用于在发送给终端用户之前压缩响应内容。

一个过滤器可能由一个前处理器(在动作之前执行)和/或一个后处理器(在动作之后执行)。过滤器本质上是一种特殊的行为。因此,使用过滤器和使用行为是一样的。

假设我们有一个web应用,它提供了一个用户界面,只在指定的小时内工作,例如从上午10点到下午6点。

准备

按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。

如何做…

  1. 创建一个控制器@app/controllers/TestController.php
  1. <?php
  2. namespace app\controllers;
  3. use app\components\CustomFilter;
  4. use yii\helpers\Html;
  5. use yii\web\Controller;
  6. class TestController extends Controller
  7. {
  8. public function behaviors()
  9. {
  10. return [
  11. 'access' => [
  12. 'class' => CustomFilter::className(),
  13. ],
  14. ];
  15. }
  16. public function actionIndex()
  17. {
  18. return $this->renderContent(Html::tag('h1',
  19. 'This is a test content'
  20. ));
  21. }
  22. }
  1. 创建一个新的过滤器@app/components/CustomFilter.php
  1. <?php
  2. namespace app\components;
  3. use Yii;
  4. use yii\base\ActionFilter;
  5. use yii\web\HttpException;
  6. class CustomFilter extends ActionFilter
  7. {
  8. const WORK_TIME_BEGIN = 10;
  9. const WORK_TIME_END = 18;
  10. protected function canBeDisplayed()
  11. {
  12. $hours = date('G');
  13. return $hours >= self::WORK_TIME_BEGIN && $hours <= self::WORK_TIME_END;
  14. }
  15. public function beforeAction($action)
  16. {
  17. if (!$this->canBeDisplayed())
  18. {
  19. $error = 'This part of website works from '
  20. . self::WORK_TIME_BEGIN . ' to '
  21. . self::WORK_TIME_END . ' hours.';
  22. throw new HttpException(403, $error);
  23. }
  24. return parent::beforeAction($action);
  25. }
  26. public function afterAction($action, $result)
  27. {
  28. if (Yii::$app->request->url == '/test/index') {
  29. Yii::trace("This is the index action");
  30. }
  31. return parent::afterAction($action, $result);
  32. }
  33. }
  1. 如果你在指定的时间之外访问页面,你将得到如下结果:

创建一个自定义过滤器 - 图1

工作原理…

首先,我们添加一些代码到我们的控制器中,它实现了我们的自定义过滤器:

  1. public function behaviors()
  2. {
  3. return [
  4. 'access' => [
  5. 'class' => CustomFilter::className(),
  6. ],
  7. ];
  8. }

默认情况下,过滤器会应用到控制器所有的动作上,但是我们可以指定哪些动作可以被应用,或者哪些动作不被应用。

你有两个动作——beforeActionafterAction。第一个会在控制器动作执行之前运行,第二个会在之后运行。

在我们的简单的例子中,我们定义了一个条件,如果时间早于早上10点,不允许访问网站,并且在after方法中,我们只是运行了一个trace方法,如果当前路径是test/index的话。

你可以在debugger中看到这个结果,在log部分:

创建一个自定义过滤器 - 图2

在真实的应用中,过滤器是比较复杂的,并且,Yii2提供了需要内置的过滤器,例如core、authentication、content negotiator,HTTP cache end等等。

参考

欲了解更多信息,参考http://www.yiiframework.com/doc-2.0/guidestructure-filters.html