创建一个自定义过滤器
过滤器是一种对象,它会在控制器动作之前或者之后运行。例如,一个访问控制过滤器可能会在动作之前运行,确保它们只能被特殊的终端用户访问;一个内容压缩过滤器可能会在动作之后运行,用于在发送给终端用户之前压缩响应内容。
一个过滤器可能由一个前处理器(在动作之前执行)和/或一个后处理器(在动作之后执行)。过滤器本质上是一种特殊的行为。因此,使用过滤器和使用行为是一样的。
假设我们有一个web应用,它提供了一个用户界面,只在指定的小时内工作,例如从上午10点到下午6点。
准备
按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
如何做…
- 创建一个控制器
@app/controllers/TestController.php:
<?phpnamespace app\controllers;use app\components\CustomFilter;use yii\helpers\Html;use yii\web\Controller;class TestController extends Controller{public function behaviors(){return ['access' => ['class' => CustomFilter::className(),],];}public function actionIndex(){return $this->renderContent(Html::tag('h1','This is a test content'));}}
- 创建一个新的过滤器
@app/components/CustomFilter.php:
<?phpnamespace app\components;use Yii;use yii\base\ActionFilter;use yii\web\HttpException;class CustomFilter extends ActionFilter{const WORK_TIME_BEGIN = 10;const WORK_TIME_END = 18;protected function canBeDisplayed(){$hours = date('G');return $hours >= self::WORK_TIME_BEGIN && $hours <= self::WORK_TIME_END;}public function beforeAction($action){if (!$this->canBeDisplayed()){$error = 'This part of website works from '. self::WORK_TIME_BEGIN . ' to '. self::WORK_TIME_END . ' hours.';throw new HttpException(403, $error);}return parent::beforeAction($action);}public function afterAction($action, $result){if (Yii::$app->request->url == '/test/index') {Yii::trace("This is the index action");}return parent::afterAction($action, $result);}}
- 如果你在指定的时间之外访问页面,你将得到如下结果:

工作原理…
首先,我们添加一些代码到我们的控制器中,它实现了我们的自定义过滤器:
public function behaviors(){return ['access' => ['class' => CustomFilter::className(),],];}
默认情况下,过滤器会应用到控制器所有的动作上,但是我们可以指定哪些动作可以被应用,或者哪些动作不被应用。
你有两个动作——beforeAction和afterAction。第一个会在控制器动作执行之前运行,第二个会在之后运行。
在我们的简单的例子中,我们定义了一个条件,如果时间早于早上10点,不允许访问网站,并且在after方法中,我们只是运行了一个trace方法,如果当前路径是test/index的话。
你可以在debugger中看到这个结果,在log部分:

在真实的应用中,过滤器是比较复杂的,并且,Yii2提供了需要内置的过滤器,例如core、authentication、content negotiator,HTTP cache end等等。
参考
欲了解更多信息,参考http://www.yiiframework.com/doc-2.0/guidestructure-filters.html。
