This article describes how to use filters in the PHP Yii Framework. Some Common Core filters are listed in this article. For more information, see
Yii filter introduction
A filter is a piece of code that can be configured to be executed before or after the controller action is executed. For example, the access control filter will be executed to ensure that the user has passed authentication before the action of the request is executed; the performance filter can be used to measure the time taken by the controller for execution.
An action can have multiple filters. The filter execution sequence is the order in which they appear in the filter list. The filter can prevent the action and other filters from being executed.
The filter can be written in two ways:
- Method-based filter
- Filters based on custom filters
Regardless of the filter, the public function filters () method of the controller must be rewritten in the controller to set which filter takes effect for which action.
Method-based filter
Three steps are required to compile a method-based filter:
Write an Action in the controller );
Compile a filter function in the controller. the function name must be prefixed with filter, for example, function filterAccessControl ();
Override the filters () method of the parent class CController to define the relationship between filters and actions;
Instance:
<? Php class UserController extends CController {*** Step 1: Create an action */function actionAdd () {echo "actionAdd" ;}/ *** Step 2: create a method-based filter */public function filterAddFilter ($ filterChain) {echo "method-based filter UserController. filterAdd
"; $ FilterChain-> run ();}/*** Step 3: override the filters () method of the parent class CController and define the relationship between filters and actions * @ see CController :: filters () */public function filters () {return array (// defines the association between filters and actions 'addfilter + add', // array (// 'application. filters. testfilter ',//),);}}
Custom filter class
To customize the filter class, you must write a filter class separately, inherit from the CFilter class, and override some methods in the CFilter class. You can take a look at the CFilter class code, which is easy to understand.
Custom filter instance:
<?php class TestFilter extends CFilter{ /** * Performs the pre-action filtering. * @param CFilterChain $filterChain the filter chain that the filter is on. * @return boolean whether the filtering process should continue and the action * should be executed. */ protected function preFilter($filterChain) { echo "--->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.
"; } }
Register the binding relationship between the custom filter and the action in the controller:
/*** Step 3: override the filters () method of the parent class CController and define the relationship between filters and actions * @ see CController: filters () */ublic function filters () {return array (// define the association between filters and actions 'addfilter + add', array ('application. filters. testfilter ',),);
I customized a filter: TestFilter, which inherits the CFilter class and overwrites two main methods of the CFilter class: preFilter (front controller, run before the action is executed) and postFilter (back controller, after the action is executed ).
Execution sequence of two controllers
If I bind the custom filter class written above to the actionAdd action, the custom filter inherits from the CFilter parent class two methods: preFilter and postFilter, what is the execution sequence between the bound actionAdd and the bound actionAdd?
The execution sequence is CFilter: preFilter ---------> UserController: actionAdd ---------> CFilter: postFilter.
That is to say, the filter operation can be performed before and after the action is executed.
In the beginning of this article, how does one achieve "filter can stop the action and other filter execution?
After reading the official comments of CFilter: preFilter, you will know:
@ Return boolean whether the filtering process shocould continue and the action shocould be executed.
CFilter: preFilter function default return
True; that is, the action following and the Post filter are executed by default. In the custom filter class, rewrite the CFilter: preFilter method and return
False; you can stop the following actions and filters from being executed!
Use filter
Filters are essentially a special type of behavior, so the use of filters is the same as the use of behavior. You can overwrite its yii \ base \ Controller: behaviors () method in the Controller class to declare the filter, as shown below:
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'); }, ], ];}
The filter of the controller class applies all the actions of the class by default. you can configure the yii \ base \ ActionFilter: only attribute to specify the actions applied by the controller. In the preceding example, the HttpCache filter applies only to the index and view actions. You can also configure the yii \ base \ ActionFilter: failed t attribute so that some actions do not execute the filter.
In addition to controllers, you can declare the filter in the module or application body. After the declaration, the filter applies to all controller actions of the module or application subject, unless the yii \ base \ ActionFilter: only and yii \ base \ ActionFilter of the filter are configured as above:: T t attribute.
Supplement: declare the filter in the module or application body, and use routing to replace the action ID in the yii \ base \ ActionFilter: only and yii \ base \ ActionFilter: unique T attributes, because only the action ID is used in the module or application body and the specific action cannot be specified uniquely ..
When an action has multiple filters, it is executed according to the following rules:
Pre-filter
- The filters listed by behaviors () in the application body are executed in sequence.
- Filters listed by behaviors () in the execution module in sequence.
- Execute the filters listed by behaviors () in the controller in sequence.
- If any filter stops, the following filters (including pre-filter and post-filter) will not be executed.
- The action is successfully performed after pre-filtering.
Filter back
- The filter listed by behaviors () in the reverse execution controller.
- Filters listed by behaviors () in the reverse execution module.
- Execute the filters listed by behaviors () in reverse order.
Create filter
Inherit the yii \ base \ ActionFilter class and overwrite the yii \ base \ ActionFilter: beforeAction () and/or yii \ base \ ActionFilter: afterAction () methods to create action filters, the former is executed before the action is executed, and the latter is executed after the action is executed. Yii \ base \ ActionFilter: beforeAction () return value determines whether the action should be executed. if it is false, subsequent filters and actions will not be executed.
The following example declares a filter that records the execution time log of an action.
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); }}
Core filter
Yii provides a set of common filters. in the yii \ filters namespace, we will briefly introduce these filters.
1. yii \ filters \ AccessControl
AccessControl provides access control based on yii \ filters \ AccessControl: rules. In particular, before an action is executed, access control detects all the rules and finds the first rule that complies with the context variables (such as the user IP address and logon status, to determine whether to allow or deny the execution of the request. If no rule is met, the access will be rejected.
The following example indicates that authenticated users are allowed to access the create and update actions, and other users are denied to access these actions.
Use yii \ filters \ AccessControl; public function behaviors () {return ['access' => ['class' => AccessControl: className (), 'only' => ['create', 'update'], 'rules' => [// allow authenticated users ['allow' => true, 'roles '=> [' @ '],], // other users are prohibited by default],],];}
2. authentication method filter
The authentication method filter authenticates a user through HTTP Basic Auth or OAuth 2. the authentication method filter class is in the yii \ filters \ auth namespace.
The following example shows that you can use yii \ filters \ auth \ HttpBasicAuth to authenticate a user, which uses a token based on the HTTP basic authentication method. Note that to run the yii \ web \ User: identityClass class, the yii \ web \ IdentityInterface: findIdentityByAccessToken () method must be implemented.
use yii\filters\auth\HttpBasicAuth;public function behaviors(){ return [ 'basicAuth' => [ 'class' => HttpBasicAuth::className(), ], ];}
Authentication method filters are usually used in implementing RESTful APIs.
3. yii \ filters \ ContentNegotiator
ContentNegotiator supports response content format processing and language processing. Check the GET parameter and Accept HTTP header to determine the response content format and language.
The following example shows how to configure ContentNegotiator to support JSON and XML response formats and English (US) and German.
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', ], ], ];}
The response format and language are much easier to detect during the application subject lifecycle. Therefore, ContentNegotiator designs a filter that can be called by the bootstrap startup component. As shown in the following example, you can configure it on the application subject.
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', ], ], ],];
Supplement: if the content format and language are not detected in the request, use the first configuration item formats and ages.
4. yii \ filters \ HttpCache
HttpCache uses the Last-Modified and Etag HTTP headers to implement client caching. For example:
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 caches the entire page on the server. As shown in the following example, PageCache is applied to the index action, and the number of records cached for the entire page changes in 60 s or after. It also saves different page versions based on different application languages.
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 limits the rate based on the bucket leakage algorithm.
7. yii \ filters \ VerbFilter
VerbFilter checks whether the HTTP request method of the request action can be executed. if not, an HTTP 405 exception is thrown. In the following example, VerbFilter specifies the request method allowed by the CRUD action.
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 allows many resources (such as fonts and JavaScript) of a webpage to be accessed by other domain names. In particular, The XMLHttpRequest mechanism can be used for JavaScript's AJAX calls. because of the same-origin security policy, this cross-origin request is forbidden by the web browser. CORS defines which cross-origin requests are allowed and disabled when the browser interacts with the server.
Yii \ filters \ Cors should be defined before the authorization/authentication filter to ensure that the CORS header is sent.
use yii\filters\Cors;use yii\helpers\ArrayHelper;public function behaviors(){ return ArrayHelper::merge([ [ 'class' => Cors::className(), ], ], parent::behaviors());}
Cors can be converted to cors attributes.
- Cors ['origin']: defines an array of allowed sources, which can be ['*'] (any user) or ['http: // www.myserver.net ', 'http: // www.myotherserver.com ']. the default value is ['*'].
- Cors ['access-Control-Request-method']: an array of permitted actions, such as ['GET', 'options', 'head']. the default value is ['GET', 'post', 'put', 'Patch ', 'delete', 'head', 'options'].
- Cors ['access-Control-Request-headers']: allows an array of Request Headers, you can specify headers of all types for ['*'] or ['X-Request-. the default value is ['*'].
- Cors ['access-Control-Allow-credentials']: specifies whether the current request uses a certificate. this parameter can be set to true, false, or null (not set). The default value is null.
- Cors ['access-Control-Max-age']: defines the validity period of the request. the default value is 86400.
For example, CORS that allows source to be http://www.myserver.net and method to GET, HEAD, and OPTIONS is as follows:
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());}
You can override the default parameters to adjust the CORS header for each action. For example, add the Access-Control-Allow-Credentials parameter for the login action as follows:
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());}