过滤器是在 控制器操作 前后运行的对象。例如,访问控制过滤器可以在操作之前运行,以确保允许特定最终用户访问这些操作;内容压缩过滤器可以在操作之后运行,以在将响应内容发送给最终用户之前压缩响应内容。
过滤器可能包含一个预过滤器(在操作之前 应用的过滤逻辑)和/或一个后过滤器(在操作之后 应用的逻辑)。
过滤器本质上是一种特殊类型的 行为。因此,使用过滤器与 使用行为 相同。您可以在控制器类中通过重写其 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');
},
],
];
}
默认情况下,在控制器类中声明的过滤器将应用于该控制器中的所有操作。但是,您可以通过配置 only 属性来显式指定应应用过滤器的操作。在上面的示例中,HttpCache
过滤器仅应用于 index
和 view
操作。您还可以配置 except 属性以防止某些操作被过滤。
除了控制器之外,您还可以在 模块 或 应用程序 中声明过滤器。当您这样做时,过滤器将应用于属于该模块或应用程序的所有控制器操作,除非您配置过滤器的 only 和 except 属性,如上面所述。
注意:当在模块或应用程序中声明过滤器时,您应该使用 路由 而不是操作 ID 在 only 和 except 属性中。这是因为操作 ID 无法完全指定模块或应用程序范围内的操作。
当为单个操作配置多个过滤器时,它们将根据下面描述的规则应用
behaviors()
中列出的顺序应用在应用程序中声明的过滤器。behaviors()
中列出的顺序应用在模块中声明的过滤器。behaviors()
中列出的顺序应用在控制器中声明的过滤器。behaviors()
中列出的反向顺序应用在控制器中声明的过滤器。behaviors()
中列出的反向顺序应用在模块中声明的过滤器。behaviors()
中列出的反向顺序应用在应用程序中声明的过滤器。要创建一个新的操作过滤器,请从 yii\base\ActionFilter 扩展并覆盖 beforeAction() 和/或 afterAction() 方法。前者将在操作运行之前执行,而后者将在操作运行之后执行。 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::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}
Yii 提供了一组常用的过滤器,主要位于yii\filters
命名空间下。在下面,我们将简要介绍这些过滤器。
AccessControl 基于一组 规则 提供简单的访问控制。特别地,在执行操作之前,AccessControl 将检查列出的规则,并找到第一个与当前上下文变量(如用户 IP 地址、用户登录状态等)匹配的规则。匹配的规则将决定是否允许或拒绝执行请求的操作。如果没有规则匹配,则将拒绝访问。
以下示例显示了如何允许经过身份验证的用户访问create
和update
操作,同时禁止所有其他用户访问这两个操作。
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['create', 'update'],
'rules' => [
// allow authenticated users
[
'allow' => true,
'roles' => ['@'],
],
// everything else is denied by default
],
],
];
}
有关一般访问控制的更多详细信息,请参阅 授权 部分。
身份验证方法过滤器用于使用各种方法对用户进行身份验证,例如 HTTP Basic Auth、OAuth 2。这些过滤器类都在yii\filters\auth
命名空间下。
以下示例显示了如何使用 yii\filters\auth\HttpBasicAuth 使用基于 HTTP Basic Auth 方法的访问令牌对用户进行身份验证。请注意,为了使此方法正常工作,您的 用户身份类 必须实现 findIdentityByAccessToken() 方法。
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
return [
'basicAuth' => [
'class' => HttpBasicAuth::class,
],
];
}
身份验证方法过滤器通常用于实现 RESTful API。有关更多详细信息,请参阅 RESTful 身份验证 部分。
ContentNegotiator 支持响应格式协商和应用程序语言协商。它将尝试通过检查GET
参数和Accept
HTTP 头来确定响应格式和/或语言。
在以下示例中,ContentNegotiator 配置为支持 JSON 和 XML 响应格式,以及英语(美国)和德语。
use yii\filters\ContentNegotiator;
use yii\web\Response;
public function behaviors()
{
return [
[
'class' => ContentNegotiator::class,
'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::class,
'formats' => [
'application/json' => Response::FORMAT_JSON,
'application/xml' => Response::FORMAT_XML,
],
'languages' => [
'en-US',
'de',
],
],
],
];
信息:如果无法从请求中确定首选内容类型和语言,则将使用 formats 和 languages 中列出的第一个格式和语言。
HttpCache 通过使用Last-Modified
和Etag
HTTP 头来实现客户端缓存。例如,
use yii\filters\HttpCache;
public function behaviors()
{
return [
[
'class' => HttpCache::class,
'only' => ['index'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('user')->max('updated_at');
},
],
];
}
有关使用 HttpCache 的更多详细信息,请参阅 HTTP 缓存 部分。
PageCache 实现整个页面的服务器端缓存。在以下示例中,PageCache 应用于index
操作,以将整个页面缓存最多 60 秒,或者直到post
表中的条目数量发生变化。它还根据选择的应用程序语言存储页面的不同版本。
use yii\filters\PageCache;
use yii\caching\DbDependency;
public function behaviors()
{
return [
'pageCache' => [
'class' => PageCache::class,
'only' => ['index'],
'duration' => 60,
'dependency' => [
'class' => DbDependency::class,
'sql' => 'SELECT COUNT(*) FROM post',
],
'variations' => [
\Yii::$app->language,
]
],
];
}
有关使用 PageCache 的更多详细信息,请参阅 页面缓存 部分。
RateLimiter 基于 漏桶算法 实现速率限制算法。它主要用于实现 RESTful API。有关使用此过滤器的详细信息,请参阅 速率限制 部分。
VerbFilter 检查 HTTP 请求方法是否被请求的操作允许。如果不允许,它将抛出一个 HTTP 405 异常。在以下示例中,VerbFilter 声明为指定 CRUD 操作的典型允许请求方法集。
use yii\filters\VerbFilter;
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'index' => ['get'],
'view' => ['get'],
'create' => ['get', 'post'],
'update' => ['get', 'put', 'post'],
'delete' => ['post', 'delete'],
],
],
];
}
跨域资源共享 CORS 是一种机制,允许网页上的许多资源(例如字体、JavaScript 等)从资源来源域之外的另一个域进行请求。特别是,JavaScript 的 AJAX 调用可以使用 XMLHttpRequest 机制。否则,根据同源策略,此类“跨域”请求将被 Web 浏览器禁止。CORS 定义了一种浏览器和服务器可以交互的方式,以确定是否允许跨域请求。
Cors 过滤器 应该在身份验证/授权过滤器之前定义,以确保 CORS 头部始终被发送。
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::class,
],
], parent::behaviors());
}
如果您想将 CORS 过滤器添加到 API 中的 yii\rest\ActiveController 类,请查看有关 REST 控制器 的部分。
可以使用 $cors 属性调整 CORS 过滤。
cors['Origin']
:用于定义允许来源的数组。可以是['*']
(所有人)或['https://www.myserver.net', 'https://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
。例如,允许源为 https://www.myserver.net
的 CORS,方法为GET
、HEAD
和OPTIONS
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::class,
'cors' => [
'Origin' => ['https://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::class,
'cors' => [
'Origin' => ['https://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
],
'actions' => [
'login' => [
'Access-Control-Allow-Credentials' => true,
]
]
],
], parent::behaviors());
}
发现错别字或您认为此页面需要改进?
在 github 上编辑它 !
在“创建过滤器”部分,我认为
afterAction()
函数应该是public function afterAction($action, $result)
{ $time = microtime(true) - $this->_startTime; **$result =** Yii::debug("Action '{$action->uniqueId}' spent **{$time}** second."); return parent::afterAction($action, $result); }
.. 还是我错了?
@Yannis Tambakis:不,
Yii::debug()
不会返回任何东西,它会将消息记录到某个文件或其他地方(取决于您如何配置日志记录器)。操作结果保持不变,即不会被此过滤器更改。要发表评论,请 注册 或 登录。