Yii中的过滤器是指,通过配置,在一个控制器的动作被执行之前或者之后执行的一小段代码 。一个例子是,如果我们想要在某个动作执行后额外记录些什么,或者执行一些审核逻辑,可以编写一个简单的审计过滤器来进行这个动作之后的处理任务。
- beforeValidate 和afterValidate
-
beforeSave 和 afterSave : 这两个将在保存 AR 实例之前和之后被调用。
-
beforeDelete 和 afterDelete : 这两个将在一个 AR 实例被删除之前和之后被调用。
-
afterConstruct : 这个将在每个使用
new
操作符创建 AR 实例后被调用 。 -
beforeFind : 这个将在一个 AR 查找器被用于执行查询(例如
find()
,findAll()
)之前被调用。 -
afterFind : 这个将在每个 AR 实例作为一个查询结果创建时被调用。
尽量不要用过滤器,过滤器是全局的,可能对其他业务操作造成影响
CWebUser
afterLogin() 用户成功登录后被调用的方法。 CWebUser
afterLogout() 用户登出后被调用的方法。 CWebUser
beforeLogin() 在用户登录那一时刻前被调用的方法。 CWebUser
beforeLogout() 当用户调用logout注销时,将调用该方法。
model中
protected function afterFind() {
if ($this->getScenario() == 'findYuan') {
$this->proxy_charges = $this->proxy_charges / 100;
}
return parent::afterFind();
}
protected function beforeSave() {
if ($this->isNewRecord) {
$this->reg_date = time();
$this->passwd = $this->hasPassword($this->passwd1);
$this->credit = 0;
} else{
$this->modify_date = time();
}
if ($this->getScenario() == 'changePassword' || $this->getScenario() == 'resetPassword') {
$this->passwd = $this->hasPassword($this->passwd1);
}
return parent::beforeSave();
}
protected function beforeFind() {
parent::beforeFind();
$this->getDbCriteria()->addColumnCondition(array('type'=>self::TYPE_WIKI));
return true;
}
protected function afterSave(){
parent::afterSave();
if(!$this->isNewRecord){
$this->dbConnection->createCommand('DELETE FROM PostTag WHERE postId='.$this->id)->execute();
}
return true;
}
一个普遍的例子就是,当我们要求执行某个特定的控制器动作之前,用户必须已经登录,那么可以写一个简单的访问过滤器在这个动作执行之前来检查这个要求。
- beforeAction
- afterAction
controller中
public function beforeAction($action){
if(Yii::app()->user->isGuest&&$action->getId()!='login'){
$this->redirect(Yii::app()->loginUrl);
}
return parent::beforeAction($action);
}
Filter过滤器主要是控制访问
YII自定义登录过滤器
<?php
class SessionCheckFilter extends CFilter
{
protected function preFilter($filterChain)
{
if (Yii::app()->user->id > 0) {
$filterChain->run();
} else {
Yii::app()->getController()->redirect(array('user/login'));
}
return true;
}
}
然后在你的Controller中通过filters方法使用,所有XXController继承Controller即可
<?php
class Controller extends CController
{
public function filters()
{
return array(
array('application.filters.SessionCheckFilter - login, register')
);
}
}
<?php
class TestController extends CController
{
//该方法判断用户是否登录
public function filterInlineFilterName($filterChain)
{
if (Yii::app()->user->isGuest && !in_array($filterChain->action->id, $this->inlineFilterNameAction())) {
Yii::app()->user->loginRequired(); //封装了登录的url
}
$filterChain->run(); //参数$filterChain就是执行该filter的action实例,调用$filterChain->run()其实就是执行该action了。
}
public function filters()
{
return array('inlineFilterName');
}
public function inlineFilterNameAction()
{ //返回要执行过滤的action
return array('action1', 'action2', 'action3');
}
}
这样就可以做到对指定的action添加自定义的过滤规则了。
其实,Yii里已经封装好了一个过滤类,这里带大家看看它是怎样实现的,其实原理和上面一模一样。我们先来看看CController里的public void filterAccessControl(CFilterChain $filterChain) 方法:
public function filterAccessControl($filterChain)
{
$filter=new CAccessControlFilter;
$filter->setRules($this->accessRules());
$filter->filter($filterChain);
}
可以看到,它是以filter开头的函数,大家知道它是干嘛的了吧?该方法实例化了一个CAccessControlFilter 类,该类就是处理过滤规则的,然后把$this->accessRules()作为一个参数付给 $filter->setRules()方法。 下面来看看accessRules()方法的写法:
public function accessRules()
{
return array(
'allow', // or 'deny'
//可选规则,本规则适用于列出的所有动作ID(不区分大小写)
//如果未指定此项,则规则适用于所有动作。
'actions' => array('edit', 'delete'),
//可选规则,本规则适用于列出的所有控制器ID(不区分大小写)
'controllers' => array('post', 'admin/user'),
//可选规则,本规则适用于列出的所有用户ID(不区分大小写)
//使用*号表示所有用户,?号表示来宾用户,@表示通过身份验证的用户。
'users' => array('thomas', 'kevin'),
//可选规则,本规则适用于列出的所有角色(区分大小写)。
'roles' => array('admin', 'editor'),
//可选规则,本规则适用于列出的所有IP地址。
//如127.0.0.1, 127.0.0.*
'ips' => array('127.0.0.1'),
//可选规则,本规则适用于列出的所有请求类型(区分大小写)。
'verbs' => array('GET', 'POST'),
//可选规则,一个PHP表达式,其值表示此规则是否适用
'expression' => '!$user->isGuest && $user->level==2',
//可选规则,显示自定义的错误消息
//自1.1.1版后,此选项开始使用。
'message' => 'Access Denied.',
);
}
好了,这下对Yii的过滤规则大家了解了吧?试着写写吧