Home Backend Development PHP Tutorial How to use join and joinwith multi-table association queries in Yii2

How to use join and joinwith multi-table association queries in Yii2

Dec 29, 2017 pm 05:57 PM
join yii2

This article mainly introduces the use of multi-table association queries (join, joinwith) in Yii2. Friends in need can refer to it. I hope to be helpful.

Table structure

Now there are customer table, order table, book table, author table,

Customer table Customer ( id customer_name)
Order tableOrder (id order_name customer_id book_id)
Book table(id book_name author_id)
Author table(id author_name)

Model definition

The following are the definitions of these four models, only the relationships among them are written

Customer


# #

class Customer extends \yii\db\ActiveRecord
{
// 这是获取客户的订单,由上面我们知道这个是一对多的关联,一个客户有多个订单
public function getOrders()
{
// 第一个参数为要关联的子表模型类名,
// 第二个参数指定 通过子表的customer_id,关联主表的id字段
return $this->hasMany(Order::className(), ['customer_id' => 'id']);
}
}
Copy after login

Order

##

class Order extends \yii\db\ActiveRecord
{
// 获取订单所属用户
public function getCustomer()
{
//同样第一个参数指定关联的子表模型类名
//
return $this->hasOne(Customer::className(), ['id' => 'customer_id']);
}
// 获取订单中所有图书
public function getBooks()
{
//同样第一个参数指定关联的子表模型类名
//
return $this->hasMany(Book::className(), ['id' => 'book_id']);
}
}
Copy after login

Book

##
class Book extends \yii\db\ActiveRecord
{
// 获取图书的作者
public function getAuthor()
{
//同样第一个参数指定关联的子表模型类名
return $this->hasOne(Author::className(), ['id' => 'author_id']);
}
}
Copy after login


Author

class Autor extends \yii\db\ActiveRecord
{
}
Copy after login


hasMany, hasOne uses the table in

Yii2 There are two types of associations, which are used to specify the association between two models.

One-to-many: hasMany

One-to-one: hasOne

Return results: The return results of these two methods are yii\db\ ActiveQuery object

The first parameter: the class name of the associated model.

The second parameter: is an array, where the key is the attribute in the associated model and the value is the attribute in the current model.

Associated use

Now we get all the order information of a customer

// 获取一个客户信息
$customer = Customer::findOne(1);
$orders = $customer->orders; // 通过在Customer中定义的关联方法(getOrders())来获取这个客户的所有的订单。
Copy after login

The above two lines of code will generate the following sql statement

SELECT * FROM customer WHERE id=1;
SELECT * FROM order WHERE customer_id=1;
Copy after login


Associated result cache

If the customer's order changes, we call

$orders = $customer->orders;
Copy after login

again and you will find that there is no change when you get the order again. The reason is that the database will only be queried when $customer->orders is executed for the first time, and the results will be cached, and sql will not be executed during subsequent queries.

So what if I want to execute sql again? You can execute

unset($customer->orders);
$customer->orders;
Copy after login

and then you can fetch data from the database.

Define multiple associations

Similarly, we can also define multiple associations in Customer. If the total number of orders is returned greater than 100.


class Customer extends \yii\db\ActiveRecord
{
public function getBigOrders($threshold = 100)
{
return $this->hasMany(Order::className(), ['customer_id' => 'id'])
->where('subtotal > :threshold', [':threshold' => $threshold])
->orderBy('id');
}
}
Copy after login


The two associated access methods

are as above, if you use

$customer->bigOrders
Copy after login

will get all orders greater than 100. If you want to return orders greater than 200, you can write like this

$orders = $customer->getBigOrders(200)->all();
Copy after login

As you can see from the above, there are two ways to access an association

If When called as a function, an ActiveQuery object ($customer->getOrders()->all()) will be returned.

If called as an attribute, the result of the model will be returned directly ( $customer->orders)

With the use of the following code, it is to take a customer's order

// 执行sql语句: SELECT * FROM customer WHERE id=1
$customer = Customer::findOne(1);
//执行sql:SELECT * FROM order WHERE customer_id=1
$orders1 = $customer->orders;
//这个不会执行sql,直接使用上面的缓存结果
$orders2 = $customer->orders;
Copy after login

If we want to take out 100 users now , and then access each user's order. From the above understanding, we may write the following code

// 执行sql语句: SELECT * FROM customer LIMIT 100
$customers = Customer::find()->limit(100)->all();
foreach ($customers as $customer) {
// 执行sql: SELECT * FROM order WHERE customer_id=...
$orders = $customer->orders;
// 处理订单。。。
}
Copy after login

However, if we really want to write it like this, it will be in every foreach Each loop executes SQL once to query the data in the database. Because each $customer object is different.

In order to solve the above problem, you can use yii\db\ActiveQuery::with().

The width parameter is the name of the relationship, which is the getOrders defined in the model, the orders and customer in getCustomer

// 先执行sql: SELECT * FROM customer LIMIT 100;
// SELECT * FROM orders WHERE customer_id IN (1,2,...)
$customers = Customer::find()->limit(100)
->with('orders')->all();
foreach ($customers as $customer) {
// 在这个循环的时候就不会再执行sql了
$orders = $customer->orders;
// ...handle $orders...
}
Copy after login

If select is used To specify the returned columns, be sure to ensure that the returned columns contain the associated fields of the associated model, otherwise the Model

$orders = Order::find()->select(['id', 'amount'])->with('customer')->all();
// $orders[0]->customer 的结果将会是null
// 因为上面的select中没有返回所关联的模型(customer)中的指定的关联字段。
// 如果加上customer_id,$orders[0]->customer就可以返回正确的结果
$orders = Order::find()->select(['id', 'amount', 'customer_id'])->with('customer')->all();
Copy after login

## of the associated table will not be returned.
#Add filter conditions to with

Query an order with more than 100 customers

//首先执行sql: SELECT * FROM customer WHERE id=1
$customer = Customer::findOne(1);
// 再执行查询订单的sql语句:SELECT * FROM order WHERE customer_id=1 AND subtotal>100
$orders = $customer->getOrders()->where('subtotal>100')->all();
Copy after login

Query 100 customers, The total number of orders for each customer is greater than 100


// 下面的代码会执行sql语句: 
// SELECT * FROM customer LIMIT 100
// SELECT * FROM order WHERE customer_id IN (1,2,...) AND subtotal>100
$customers = Customer::find()->limit(100)->with([
'orders' => function($query) {
$query->andWhere('subtotal>100');
},
])->all();
Copy after login

Here the width parameter is an array, the key is the associated name, and the value is the callback function.


That is to say, for the ActiveQuery returned by the orders association, execute $query->andWhere('subtotal>100');

Use joinWith to perform table processing Association

We all know that we can use join on to write associations between multiple tables. First look at the declaration of joinWit in yii2

joinWith( $with, $eagerLoading = true, $joinType = 'LEFT JOIN' )
Copy after login

$with The data type is a string or an array. If it is a string, it is the name of the association defined in the model (can as a sub-association).


If it is an array, the key is the association defined in the getXXX format in the model, and the value is the further callback operation for this association.

$eagerLoading Whether to load the data of the model associated in $with.

$joinType 联接类型,可用值为:LEFT JOIN、INNER JOIN,默认值为LEFT JOIN


// 订单表和客户表以Left join的方式关联。
// 查找所有订单,并以客户 ID 和订单 ID 排序
$orders = Order::find()->joinWith('customer')->orderBy('customer.id, order.id')->all();
// 订单表和客户表以Inner join的方式关联
// 查找所有的订单和书
$orders = Order::find()->innerJoinWith('books')->all();
// 使用inner join 连接order中的 books关联和customer关联。
// 并对custmer关联再次进行回调过滤:找出24小时内注册客户包含书籍的订单
$orders = Order::find()->innerJoinWith([
'books',
'customer' => function ($query) {
$query->where('customer.created_at > ' . (time() - 24 * 3600));
}
])->all();
// 使用left join连接 books关联,books关联再用left join 连接 author关联
$orders = Order::find()->joinWith('books.author')->all();
Copy after login

在实现上,Yii 先执行满足JOIN查询条件的SQL语句,把结果填充到主模型中, 然后再为每个关联执行一条查询语句, 并填充相应的关联模型。


// Order和books关联 inner join ,但不获取books关联对应的数据
$orders = Order::find()->innerJoinWith('books', false)->all();
Copy after login

On条件

在定义关联的时候还可以指定on条件


class User extends ActiveRecord
{
public function getBooks()
{
return $this->hasMany(Item::className(), ['owner_id' => 'id'])->onCondition(['category_id' => 1]);
}
}
Copy after login

在joinWith中使用


//先查询主模型(User)的数据, SELECT user.* FROM user LEFT JOIN item ON item.owner_id=user.id AND category_id=1
// 然后再根据关联条件查询相关模型数据SELECT * FROM item WHERE owner_id IN (...) AND category_id=1
// 这两个在查询的过程中都使用了 on条件。
$users = User::find()->joinWith('books')->all();
Copy after login

如果没有使用join操作,即使用的是with 或者 直接以属性来访问关联。这个时候on条件会作为where 条件。

// SELECT * FROM user WHERE id=10
$user = User::findOne(10);
Copy after login

总结

首先需要在模型中定义好关联(如getOrders中的Orders为一个关联)

然后在with或者joinWith中使用在模型中定义的关联。

其中在使用关联的时候还可以指定回调方法。

再有就是可以给关联、with、joinWith指定where或者on条件。

相关推荐:

Yii2实现QQ互联登录

Yii2使用缓存的简单解析

Yii2实现rbac权限控制

The above is the detailed content of How to use join and joinwith multi-table association queries in Yii2. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to use JOIN in MySql How to use JOIN in MySql Jun 04, 2023 am 08:02 AM

The meaning of JOIN is just like the English word "join". It joins two tables and can be roughly divided into inner join, outer join, right join, left join and natural join. First create two tables, the following is used as an example CREATETABLEt_blog(idINTPRIMARYKEYAUTO_INCREMENT,titleVARCHAR(50),typeIdINT);SELECT*FROMt_blog;+----+------+--------+| id|title|typeId|+----+-------+--------+|1|aaa|1||2|bbb|2||3|ccc|3|

How to remove jquery in yii2 How to remove jquery in yii2 Feb 17, 2023 am 09:55 AM

How to remove jquery from yii2: 1. Edit the AppAsset.php file and comment out the "yii\web\YiiAsset" value in the variable $depends; 2. Edit the main.php file and add the configuration "'yii" under the field "components" \web\JqueryAsset' => ['js' => [],'sourcePath' => null,]," to remove the jquery script.

What is the usage principle of MySQL Join? What is the usage principle of MySQL Join? May 26, 2023 am 10:07 AM

Join type leftjoin uses the left table as the driving table and the left table as the basis of the result set. The data from the right table is connected to the result set. rightjoin uses the right table as the driving table and the right table as the basis of the result set to connect the left table. The data is added to the result set innerjoin. The result set takes the intersection of the two tables fulljoin. The result set takes the union of the two tables. MySQL does not have a fulljoin. The difference between union and unionall is that union will deduplicate the crossjoin Cartesian product. If the where condition is not used, the result set will be the product and of the two associated table rows. The difference is that when crossjoin creates the result set, it will be passed according to the on condition.

How to use JOIN in MySQL How to use JOIN in MySQL Jun 03, 2023 am 09:30 AM

Introduction A's unique + AB's public B's unique + AB's public AB's public A's unique B's unique A's unique + B's unique + AB's public A's unique + B's unique Practice creating table department tables DROPTABLEIFEXISTS`dept`;CREATETABLE`dept`(`dept_id`int(11)NOTNULLAUTO_INCREMENT,`dept_name`varchar(30)DEFAULTNULL,`dept_number`int(11)DEFAULTNULL,PRIMARYKEY(`dept_id`))ENGINE =InnoDBAUT

What are mysql's join query and multiple query methods? What are mysql's join query and multiple query methods? Jun 02, 2023 pm 04:29 PM

Compared with join query and multiple queries, which one is more efficient, MySQL multi-table related query or multiple single-table query? When the amount of data is not large enough, there is no problem using join, but it is usually done on the service layer. First: the computing resources of a stand-alone database are very expensive, and the database needs to serve both writing and reading at the same time, which requires CPU consumption. In order to make the database The throughput becomes higher, and the business does not care about the delay gap of hundreds of microseconds to milliseconds. The business will put more calculations into the service layer. After all, computing resources can be easily expanded horizontally, and databases are difficult, so most The business will put pure computing operations into the service layer, and use the database as a kv system with transaction capabilities. This is a heavy business.

Use MySQL's JOIN function to join tables Use MySQL's JOIN function to join tables Jul 26, 2023 am 08:37 AM

Use MySQL's JOIN function to join tables. In MySQL, JOIN is a very common operation that allows us to join two or more tables based on the associated fields between them. This makes it easy to query and obtain relevant data from multiple tables, improving query efficiency and flexibility. This article will use code examples to demonstrate how to use MySQL's JOIN function to join tables. First create two sample tables: students and scores. The students table contains students

A few selected CTF exercises will help you learn the yii2 framework! A few selected CTF exercises will help you learn the yii2 framework! Feb 23, 2022 am 10:33 AM

This article will introduce you to the yii2 framework, share a few CTF exercises, and use them to learn the yii2 framework. I hope it will be helpful to everyone.

How to install Redis extension using YII2 framework How to install Redis extension using YII2 framework May 26, 2023 pm 06:41 PM

1. You need to download the windows version of the master branch of yii2-redis with composer 2. Unzip and copy it to vendor/yiisoft 3. Add 'yiisoft/yii2-redis'=>array('name'=>'yiisoft to extensions.php under yiisoft /yii2-redis','version'=>'2.0.

See all articles