Yii2 learning notes



Controller period


		*The pre operation of action 
		*It is suitable for unified data verification, request data acceptance, etc
		*@ param / Yii / base / action $action action class
		*@ return bool returns the true controller cycle to go on
		public function beforeAction($action)
		var_dump($action->id, $action->controller->id);
		return parent::beforeAction($action); // TODO: Change the autogenerated stub


		*Action post operation
		*It is more suitable to return to the final log collection
		*@ param / Yii / base / action $action action class
		* @param mixed $result
		* @return mixed
		public function afterAction($action, $result)
		return parent::afterAction($action, $result); // TODO: Change the autogenerated stub


Common methods of AR model

Query data

//Inquiry sheet
		$one = Post::find()->where(['id' => 1])->one();
		$one = Post::finOne(1);

		//Query multiple
		$posts = Post::find()->where(['status' => 1])->all();
		$posts = Post::findAll(['status' => 1]);

		//Query through SQL
$posts = Post::findBySql('SELECT * FROM `posts` WHERE `status` = :status', [':status' => 1])->all();

Setting of query conditions

Parameters supported by where query
  • String format, for example: ‘status = 1’
//Corresponding SQL: where status = 1
		$query->where('status = 1');
		//Using string mode, you can bind parameters
$query->where('status = :status', [':status' => 1])
  • Hash format, for example: [‘status’ = > 1, ‘type’ = > 1]

The hash format is best used to specify a simple “equal assertion” subcondition of multiple and concatenation.

//Corresponding SQL: where (` status' = 1) and (` type '= 1)
		$query->where(['status' => 1, 'type' => 1])
		//If the value is an array, it will be converted to in corresponding to SQL: where (` status' = 1) and (` type ` in (1, 2, 3))
$query->where(['status' => 1, 'type' => [1, 2, 3]])
  • For example: [‘=’,’status’, 1]

Can achieve more complex query conditions

  1. format
['operator ', operator1, operator2,...];
  1. demonstration
//SQL corresponding to a simple single query: where 'status' > = 1
		$query->where(['>=', 'status', 1])

		//SQL corresponding to multiple conditional and connections: where (` status' > = 1) and (` type '< = 3)
		$query->where(['and', ['>=', 'status', 1], ['<=', 'type', 3]])

		//Multiple conditional or connections correspond to SQL: where (` status ` in (1,3)) or (` type '> = 2)
		$query->where('or', ['in', 'status', [1, 3], ['>=', 'type', 2]])

		//SQL corresponding to complex combination: where (` create)_ type` = 6) AND (`status` = 0) AND (`is_ fail` = 0) AND (((`last_ view_ time` = 0) AND (`create_ time` <= 1503562511)) OR ((`last_ view_ time` > 0) AND (`last_ view_ time` <= 1503562511)))
		['=', 'create_type', 6],
		['=', 'status', 0],
		['=', 'is_fail', 0],
		['and', ['=', 'last_view_time', 0], ['<=', 'create_time', time()]],
		['and', ['>', 'last_view_time', 0], ['<=', 'last_view_time', time()]]
  1. Operator description

    • And and and or determine how multiple conditions are connected
    • Between and not between
    //The array needs four elements corresponding to SQL: where ` ID ` between 1 and 10
    		['between', 'id', 1, 10]
    • In and not in
    //Corresponding SQL: where 'status' in (1,3)
    		['in', 'status', [1, 3]]
    • like
    //Default corresponding SQL: where 'name' like 'username%'
    				['like', 'name', 'username'] 
    				*The second range value is an array, and multiple like statements concatenated with and will be generated
    				*Corresponding SQL: where 'name' like 'user%' and 'name' like '% name%'
    				['like', 'name', ['user', 'name']]
    				//Query corresponding SQL with prefix: where ` name ` like 'user%'
    		['like', 'name', 'user%', false]
    • Or like is the same as like, except that the second range value is an array, then multiple like statements concatenated with or will be generated
    //Corresponding SQL: where 'name' like 'user%' or 'name' like '% name%'
    				['or like', 'name', ['user', 'name']]
    				//Self defined prefix query or suffix query corresponding SQL: where 'name' like 'user%' or 'name' like 'name'
    		['or like', 'name', ['user%', '%name'], false]
    • Not like and or not like and like use the same as or like
    • Exists and not exists require an operand, which must be an instance representing the subquery yiidbquery
    //Generated SQL: 
    				WHERE EXISTS (SELECT * FROM `user` WHERE `status` = 1)
    				$queryOne = new Query();
    				$queryOne->from('user')->where(['=', 'status', 1])->one();
    $query->where(['exists', $queryOne])
    • >, >=, =, <, <=
  • And where and or where add additional conditions to the original conditions. You can call these methods multiple times to append different conditions
//Corresponding SQL: where (` status' = 1) and (` type '> = 1)
		$query->where(['=', 'status', 1]);
		$query->andWhere(['>=', 'type', 1]);

		//Corresponding SQL: where ((` status' = 1) and (` type '= 1)) or (` name' ='username ')
		$query->where(['status' => 1, 'type' => 1]);
$query->orWhere(['name' => 'username']);
  • Filterwhere filters queries (which are easier to use when users enter queries) ignores null values (null, ‘,’, ‘))
//Query criteria will not be added
		$status = '; // null,', [] will not add query conditions
		$query->filterWhere(['status' =>  $status]);

		//Add query criteria: where 'status' = 0
		$status = 0;
$query->filterWhere(['status' => $status]);
It is suggested that the where condition should be defined by passing an array in the where() method; and where() and orwhere() will increase the judgment

Query object to array

Asarray() method

In the case of no other operations on the query data, it is recommended to convert them to arrays (which can save memory)

//It's an array
$posts = Post::find()->where(['status' => 1])->asArray()->all();

Specifies the key of the array

Indexby() method

$users = User::find()->where(['status' => 1])->asArray()->indexBy('id')->all();

		//The query array
		'1' => [
		'id' => 1,
		'status' => 1,
		'username' => 'username'
		'3' => [
		'id' => 3,
		'status' => 1,
		'username' => 'my name'

		//In this way, the array is queried to determine whether the user with the specified ID has a comparison method (especially in the loop)
		if (isset($user[1])) {
Usage scenarios

Now the background program needs to display the article information, and needs to display the article author information

Structure of two tables

Article table

Field name Field description
id Article ID
user_id Article author ID
title Article title

User table

Field name Field description
id User ID
name User name
  • Scheme 1 uses table Association
//The association relationship is defined in the article model class
		class Article extends ActiveRecord
		public function getUser()
		return $this->hasOne(User::className(), ['id' => 'user_id']);

		*This indicates that only two queries are used here
		*The first time: 
		* SELECT * FROM `article` LIMIT 10
		*The second time: 
		* SELECT * FROM `user` WHERE `id` IN (1, 2, ...)
		$arrArticles = Article::find()->with('user')->limit(10)->asArray()->all();
		if ($arrArticles) {
		foreach ($arrArticles as $article) {
		if (isset($article['user'])) {
		//Use author name
  • Scheme 2 uses indexby ()
//The first step is to find out the article information
		$arrArticles = Article::find()->limit(10)->asArray()->all();

		//The second step is to get the user information
		if ($arrArticles) {
		//Get user ID 
		$arrUserIds = array_column($arrArticles, 'user_id');
		//Query customer information
		$arrUsers = User::find()->where(['id' => $arrUserIds])->indexBy('id')->asArray()->all();
		//Third, add the user name to the article information
		foreach ($arrArticles as &$value) {
		$value['user_name'] = '';
		if (isset($arrUsers[$value['user_id']])) {
		$value['user_name'] = $arrUsers[$value['user_id']]['name'];

Batch query

When dealing with big data, methods like yiidbquery:: all() are not appropriate because they read all the data into memory. To keep memory requirements low, Yii provides support for so-called batch queries. Batch queries use data cursors to fetch data in batches.

use yii\db\Query;

		$query = (new Query())

		foreach ($query->batch() as $users) {
		//$users is an array of 100 or less user table data

		// or if you want to iterate the row one by one
		foreach ($query->each() as $user) {
		//$user refers to one row of data in the user table

The yiidbquery:: batch() and yiidbquery:: each() methods will return an object that implements the iterator interface yiidbbatchqueryresult, which can be used in the foreach structure. In the first iteration, the database will execute a SQL query, and then in the remaining iterations, the data will be directly obtained from the result set in batches. By default, the size of a batch is 100, which means that a batch gets 100 rows of data. You can change the number of rows per batch by passing a value to the first parameter of the batch () or each () method.

View execution statements

//You can view it through the debug tool provided by Yii

		//Through the model class
		//View execution SQL: 
		// SELECT * FROM `user` WHERE `status` IN (1, 2)
		var_dump(User::find()->where(['status' => [1, 2, 3]])->createCommand()->getRawSql());

		//View preprocessed SQL: 
		// SELECT * FROM `user` WHERE `status` IN (:qp0, :qp1)
		var_dump(User::find()->where(['status' => [1, 2, 3]])->createCommand()->getSql());


Validation rule definition

Define format

//The first field can be a string or an array
		[[validation field], validation rule, other configuration items...]

		//Must be a single field when it is a string
		['username ','required','message '= >'user name cannot be empty']

		//Multiple field validation
[['username', 'password'], 'required']


//It is defined in the rules method of the model
		public function rules()
		return [
		//Cannot be empty
		[['username', 'passwrod'], 'required'],
		//Must be unique
		[['username'], 'unique'],

Validation rule type

General prompt information can not be filled in, and the field description information returned by attributelabels() method will be automatically matched

  • Required: required value validation
//Required value, message can be filled in
[['field name '],'required','requiredvalue '= >'required value','message '= >'prompt message']
  • Email email format verification
['email', 'email']
  • Match regular expression event verification
[['field name '],'match','pattern '= >'regular expression']
		//Regular negation
[['field name '],'match','pattern '= >'regular expression','not '= > true]
  • Verification of URL information
//Verify the address of HTTPS or http
		['field name', 'URL']

		*The input field can not be prefixed with HTTP, which is added for you by default
		*The value entered can be www.baidu.com  It can also be http://www.baidu.com
		*Input www.baidu.com  Will help you add http: // http://www.baidu.com
		[['field name '],'url','defaultscheme '= >'http']
  • Captcha verification code
['captcha ','captcha']
  • Compare
//Comparevalue comparison value operator comparison type
		['field ','compare','comparevalue '= > 30,' operator '= > >']

		//Compare the values of the two fields (the confirmation password needs to be consistent with the password)
[['confirm_password'], 'compare', 'compareAttribute' => 'password']
  • Default default value when the field is empty, the default value is assigned
//Value defines the default value
['field ','default','value '= > 30]
  • Exist to verify existence
//The validation data username must exist in the table
		['username', 'exist']

		//Define the query model and whether the user name exists in the admin table
		['username', 'exist', 'targetClass' => Admin::className()]

		//Define the fields of the data
['username', 'exist', 'targetAttribute' => 'name']
  • Unique uniqueness verification
		*Targetclass can be configured to query that table
		*Targetattribute can define the corresponding field information
['username', 'unique']
  • File file verification
		*Extension allowed file types to be uploaded
		*Other configuration items
		*Checkextensionbymimetype whether to use the MIME type to check the file type (extension)
		*Mimetypes allowed mimetypes types
		*Minsize file minimum size
		*Maxsize file maximum size
		*More configurations
[['file'], 'file', 'extensions' => ['png', 'jpg', 'gif', 'jpeg']]
  • Image image validation is inherited from file
		*Image validation is inherited from file validation
		*File defined validation configuration can be used
		*Other configurations
		* minWidth, minHeight, maxWidth, maxLength, ...
['image', 'image', 'minWidth' => 100]
  • Filter [trim]
		*Anonymous functions can be used for filter functions
		*Skip array filtering
['username', 'filter', 'filter' => 'trim', 'skipOnArray' => true]
  • Trim treatment
[['username', 'password'], 'trim']
  • In range validation
//Range defines the range value
['status', 'in', 'range' => [1, 2]]
  • Integer
['age', 'integer']
  • Number number
['money', 'number']
  • Double floating point number
['money', 'double']
  • String string validation
		*Length defines the minimum and maximum length of a string
		*Min, Max define the specified minimum and maximum length separately
['title', 'string', 'length' => [1, 2]]
  • Boolean verification
		*Is strict definition strictly validated
['field name','boolean ','truevalue' = > true, 'false value' = > false,'strict '= > true]
  • Date validation [data, time, datetime]
['start_time', 'date']
  • IP authentication
[['user_ip'], 'ip']

Custom validation rules

class User extends Model
		public function rules()
		return [
		['username', 'validateUser', 'params' => [1, 2, 3]]
		*Custom validation processing
		*The @ desc function does not accept parameters when writing
		*@ param string $attribute field name
		*Params parameter information defined in @ param mixed $params rules
		*@ param / Yii / validators / inlinevalidator $validator validation class
		public function validateUser($attribute, $params, $validator)
		if ($this->user == 2) {
		$this - > adderror ($attribute, 'cannot be equal to two');

Validation rule validation conditions

//You can define the validation conditions for the specified validation
		//Specify when server authentication takes effect (password cannot be empty when status is 1)
		'when' => function ($model) {
		return $model->status == 1;
		//When does front-end JS validation take effect
		'whenClient' => "function(attribute, value) {
		return $('#status').val() == 1;

Verification scenario

The model may be used in different scenarios. Different scenarios correspond to different business logic, and the fields and methods to be verified are different. Therefore, the verification scenario is needed

Define validation scenarios

Define validation scenarios in model

class User extends Model
		public function scenarios()
		//The validation field of default
		$scenarios = parent::scenarios();
		//At login time, verify the user name and password
		$scenarios['login'] = ['username', 'password'];
		//The user name, password and password should be verified when registering
		$scenarios['register'] = ['username', 'password', 'confirm_password'];
		return $scenarios;

Specify validation scenarios for rules

Or the model above

		*Define validation rules
		public function rules
		return [
		//Define general validation as well
		[['username', 'password'], 'trim'],
		//The validation scenario used by the on definition can be a string or an array
		[['username', 'password'], 'required', 'on' => ['login', 'register']],
		['confirm_password', 'required', 'on' => 'register'],
		['confirm_password', 'compare', 'compareAttribute' => 'password', 'on' => 'register'],
Use validation scenarios

Usually in the controller

public function actionLogin()
		//Use validation scenarios
		$user = new User();
		$user->scenario = 'login';
		//Or specify the validation scenario in the instantiation
		$user = new User(['scenario' => 'login']);
		//Assign values to the properties of the model
		$user->username = '123';
		//Call validation for display
		if ($user->validate()) {
		//Pass validation
		} else {
		//Get error information
		*The validate () method is called when you execute save()
		*Unless the save() call specifies no verification
		* $user->save(false)
		if ($user->save()) {
		}  else {
Note on the use of validation rules

Execution verification is through rules in rules, from top to bottom. If the verification fails, it will not be verified down. It is recommended that the verification of database be put to the end as far as possible

Operation of data

Block assignment

Block assignment fills all user input into a model with only one line of code

$user = new User();
		$user->attributes = Yii::$app->request->post('User', []);

		//Equivalent to
		$user = new User();
		$data = Yii::$app->request->post('User', []);
		$user->username = isset($data['username']) ? $data['username'] : null;
$user->password = isset($data['password']) ? $data['password'] : null;
  • Use the load() method
$user = new User();

		*The Yii form is used by default
		*The submitted form array should be 
		*Form element < input type = "text" name = "user [username] / >
		* [
		*      'User' => ['username' => 'username', 'password' => 'password']
		* ] 

		*No Yii form used
		* <input type="text" name="username" >
		*Corresponding to the submitted value
		* ['username' => 'username', 'password' => '']
$user->load(Yii::$app->request->post(), '');
  • Using attributes attributes
		*Attributes need to receive an array 
		*[attribute field = > corresponding value]
$user->attributes = Yii::$app->request->post('User', []);
  • Use the setattributes() method (the first two are ultimately the setattributes() methods that are called)
$user = new User();

		*You need to receive an array
		*[attribute field = > corresponding value]
Block assignment notice
  1. Only fields defined as safe can be assigned successfully
  2. In the case of no defined scenario, the field with defined rules will be considered safe and the block assignment can be successful
  3. The validation scenario is defined, and only the fields defined by the scenario can be assigned in batch

New data

$user = new User();
		$user->username = 'username';
		$user->password = 'password';

		//Or use

Modify data

  • Query object modification
$user = User::findOne(1);
		$user->username = 'username';
		$user->password = 'password';

		//Or use
  • Modify the specified data
//Change the status of the user with ID equal to 2 to 1, and the second parameter is the same as the parameter in the where() method
		$intNumber = User::updateAll(['status' => 1], ['id' => 2]]);

		//Query modification using binding parameters of characters
User::updateAll(['status' => 2], 'id=:id', [':id' => 1]);
  • Attribute value accumulation
		* updateAllCounters
		*The first parameter: the field corresponds to the accumulated positive value and the reduced value negative value
		*The second parameter: the query condition is the same as the where() method, which can be string and array
		*The third parameter: the parameter of the query binding
User::updateAllCounters(['status' => -2], 'id=:id', [':id' => 1]);

Delete data

  • Delete using query object
$user = User::findOne(1);
  • Delete specified data
User::deleteAll(['status' => 0]);

The life cycle of AR

The life cycle of AR
Understanding the life cycle of AR is very important for you to operate the database. The life cycle usually has some typical events. It is very useful for developing behaviors of AR.

  • When you instantiate a new ar object, we get the following lifecycle:

Yiidbactiverecord:: init(): a yiidbactiverecord:: event will be triggered_ Init events

  • When you query data through the find() method, each ar instance will have the following lifecycle:


  1. Yiidbactiverecord:: init(): a yiidbactiverecord:: event will be triggered_ Init events
  2. Yiidbactiverecord:: afterfind(): a yiidbactiverecord:: event will be triggered_ AFTER_ Find event
  • When data is written or updated through the yiidbactiverecord:: save() method, we get the following lifecycle:
  1. Yiidbactiverecord:: beforevalidate(): a yiidbactiverecord:: event will be triggered_ BEFORE_ Validate event
  2. Yiidbactiverecord:: aftervalidate(): a yiidbactiverecord:: event will be triggered_ AFTER_ Validate event
  3. Yiidbactiverecord:: beforesave(): a yiidbactiverecord:: event will be triggered_ BEFORE_ Insert or yiidbactiverecord:: Event_ BEFORE_ Update event
  4. Yiidbactiverecord:: aftersave(): a yiidbactiverecord:: event will be triggered_ AFTER_ Insert or yiidbactiverecord:: Event_ AFTER_ Update event
  • Finally, when we call delete() to delete data, we get the following lifecycle:
  1. Yiidbactiverecord:: beforedelete(): a yiidbactiverecord:: event will be triggered_ BEFORE_ Delete event

Perform the actual data deletion

  1. Yiidbactiverecord:: afterdelete(): a yiidbactiverecord:: event will be triggered_ AFTER_ Delete event

Reference documents

Recommended Today

Explain idea git branch backoff specified historical version

scene When I submitted this modification to the local and remote branches, I found that there were still some changes missing in this submission, or this modification was totally wrong, but I also pushed it to the remote repository. How to go back? problem How can the content that has been submitted to the repository […]