Rumah pembangunan bahagian belakang tutorial php 关于Yii2中使用join和joinwith进行多表关联查询

关于Yii2中使用join和joinwith进行多表关联查询

Jun 19, 2018 am 11:39 AM
join

这篇文章主要介绍了Yii2中多表关联查询(join、joinwith)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下

表结构

现在有客户表、订单表、图书表、作者表,

客户表Customer (id customer_name)
订单表Order (id order_name customer_id book_id)
图书表 (id book_name author_id)
作者表 (id author_name)

模型定义

下面是这4个个模型的定义,只写出其中的关联

Customer

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

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']);
}
}
Salin selepas log masuk

Book

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

Author

class Autor extends \yii\db\ActiveRecord
{
}
Salin selepas log masuk

hasMany、hasOne使用

Yii2中的表之间的关联有2种,它们用来指定两个模型之间的关联。

一对多:hasMany

一对一:hasOne

返回结果:这两个方法的返回结果都为yii\db\ActiveQuery对象

第一个参数:所关联的模型的类名称。

第二个参数:是一个数组,其中键为所关联的模型中的属性,值为当前模型中的属性。

关联的使用

现在我们获取一个客户的所有的订单信息

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

上面的两行代码会生成如下sql语句

SELECT * FROM customer WHERE id=1;
SELECT * FROM order WHERE customer_id=1;
Salin selepas log masuk

关联结果缓存

如果客户的订单改变了,我们再重新调用

$orders = $customer->orders;
Salin selepas log masuk

再次得到订单的时候你会发现没有变化。原因是只会在第一次执行$customer->orders的时候才会去数据库里面查询,然后会把结果缓存起来,以后查询的时候都不会再执行sql。

那么如果我想再次执行sql如何做呢?可以执行

unset($customer->orders);
$customer->orders;
Salin selepas log masuk

然后就可以从数据库里面取数据了。

定义多个关联

同样,我们还可以在Customer里面定义多个关联。
如返回总数大于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');
}
}
Salin selepas log masuk

关联的两种访问方式

如上面的,如果使用

$customer->bigOrders
Salin selepas log masuk

将会得到大于100的所有的订单。如果要返回大于200的订单可以这样写

$orders = $customer->getBigOrders(200)->all();
Salin selepas log masuk

从上面可以看出访问一个关联的时候有两种方法

如果以函数的方式调用,会返回一个 ActiveQuery 对象($customer->getOrders()->all())

如果以属性的方式调用,会直接返回模型的结果($customer->orders)

with的使用看如下代码,是取一个客户的订单

// 执行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;
Salin selepas log masuk

如果现在我们要取出100个用户,然后访问每个用户的订单,从上面的了解我们可能会写出如下代码

// 执行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;
// 处理订单。。。
}
Salin selepas log masuk

然而,如果真要这样写的话,会在foreach的每个循环里面都执行一次sql去数据库里面查询数据。因为每个$customer对象都是不一样的。

为了解决上面的问题 可以使用 yii\db\ActiveQuery::with()。

其中width的参数为关系的名称,也就在model里面定义的getOrders,getCustomer中的orders和customer

// 先执行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...
}
Salin selepas log masuk

如果使用了select来指定返回的列,一定要确保返回的列里面包含所关联的模型的关联字段,否则将不会返回关联的表的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();
Salin selepas log masuk

给with加过滤条件

查询一个客户大于100的订单

//首先执行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();
Salin selepas log masuk

查询100个客户的,每个客户的总合大于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();
Salin selepas log masuk

在这里width的参数为数组,键为关联的名称,值为回调函数。

也就是说 对orders这个关联返回的ActiveQuery,再执行一次$query->andWhere('subtotal>100');

使用joinWith进行表关联

我们都知道可以用join on来写多个表之间的关联。先看看yii2中joinWit的声明

joinWith( $with, $eagerLoading = true, $joinType = 'LEFT JOIN' )
Salin selepas log masuk

$with 数据类型为字符串或数组,如果为字符串,则为模型中定义的关联的名称(可以为子关联)。

如果为数组,键为model中以getXXX格式定义的关联,值为对这个关联的进一步的回调操作。

$eagerLoading 是否加载在$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();
Salin selepas log masuk

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

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

On条件

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

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

在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();
Salin selepas log masuk

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

// SELECT * FROM user WHERE id=10
$user = User::findOne(10);
Salin selepas log masuk

总结

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

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

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

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

这一部分其实非常多,也有点乱,有些功能没说说完,如三个表关联、逆关联等。

最基本的操作也就大体是这些。如果还有哪个地方想了解的,可以回帖交流。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

关于Yii实现的多级联动下拉菜单

Yii中表单用法实例

关于YII关联查询的解析

Atas ialah kandungan terperinci 关于Yii2中使用join和joinwith进行多表关联查询. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Cara menggunakan JOIN dalam MySql Cara menggunakan JOIN dalam MySql Jun 04, 2023 am 08:02 AM

Maksud JOIN sama seperti perkataan Inggeris "join". Ia bergabung dengan dua jadual dan boleh dibahagikan secara kasar kepada inner join, outer join, right join, left join dan natural join. Mula-mula buat dua jadual, berikut digunakan sebagai contoh CREATETABLEt_blog(idINTPRIMARYKEYAUTO_INCREMENT,titleVARCHAR(50),typeIdINT);SELECT*FROMt_blog;+----+------+--------+ |. id|tajuk|typeId|+----+-------+--------+|1|aaa|1||2|bbb|2||3|ccc|3 |

Apakah prinsip penggunaan MySQL Join? Apakah prinsip penggunaan MySQL Join? May 26, 2023 am 10:07 AM

Join type leftjoin menggunakan jadual kiri sebagai jadual pemanduan dan jadual kiri sebagai asas set hasil Data dari jadual kanan disambungkan kepada set hasil kanan sebagai jadual pemanduan dan jadual kanan sebagai asas set hasil untuk menyambungkan jadual kiri Data ditambah kepada set hasil innerjoin Set keputusan mengambil persilangan dua jadual fulljoin fulljoin. Kesatuan menggantikan kesatuan. Perbezaan antara kesatuan dan kesatuan adalah bahawa kesatuan akan menyahduplikasi produk Cartesian crossjoin mencipta set hasil, ia akan diluluskan mengikut syarat.

Apakah pertanyaan menyertai mysql dan kaedah pertanyaan berbilang? Apakah pertanyaan menyertai mysql dan kaedah pertanyaan berbilang? Jun 02, 2023 pm 04:29 PM

Berbanding dengan pertanyaan sertai dan berbilang pertanyaan, yang manakah lebih cekap, pertanyaan berkaitan berbilang jadual MySQL atau pertanyaan berbilang jadual tunggal? Apabila jumlah data tidak cukup besar, tiada masalah menggunakan gabungan, tetapi ia biasanya dilakukan pada lapisan perkhidmatan Pertama: sumber pengkomputeran pangkalan data yang berdiri sendiri adalah sangat mahal, dan pangkalan data perlu menyediakan kedua-dua penulisan dan membaca pada masa yang sama, yang memerlukan penggunaan CPU Untuk membuat pangkalan data Daya tampung menjadi lebih tinggi, dan perniagaan tidak mengambil berat tentang jurang kelewatan ratusan mikrosaat hingga milisaat Perniagaan akan meletakkan lebih banyak pengiraan ke dalam lapisan perkhidmatan Lagipun, sumber pengkomputeran boleh dengan mudah dikembangkan secara mendatar, dan pangkalan data adalah sukar, jadi kebanyakan perniagaan akan meletakkan operasi pengkomputeran tulen ke dalam lapisan perkhidmatan, dan menggunakan pangkalan data sebagai sistem kv dengan keupayaan transaksi.

Cara menggunakan JOIN dalam MySQL Cara menggunakan JOIN dalam MySQL Jun 03, 2023 am 09:30 AM

Pengenalan A unik + AB awam B unik + AB awam AB unik AB awam A unik B unik A unik + B unik + AB awam A unik + B unik Amalan mencipta jadual jabatan 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

Gunakan fungsi JOIN MySQL untuk menyertai jadual Gunakan fungsi JOIN MySQL untuk menyertai jadual Jul 26, 2023 am 08:37 AM

Gunakan fungsi JOIN MySQL untuk menyertai jadual Dalam MySQL, JOIN ialah operasi yang sangat biasa yang membolehkan kami menyertai dua atau lebih jadual berdasarkan medan yang berkaitan di antara mereka. Ini memudahkan untuk membuat pertanyaan dan mendapatkan data yang berkaitan daripada berbilang jadual, meningkatkan kecekapan dan fleksibiliti pertanyaan. Artikel ini akan menggunakan contoh kod untuk menunjukkan cara menggunakan fungsi JOIN MySQL untuk menyertai jadual. Mula-mula buat dua jadual sampel: pelajar dan markah. Jadual pelajar mengandungi pelajar

Bagaimana untuk meningkatkan prestasi melalui pengoptimuman JOIN dalam MySQL Bagaimana untuk meningkatkan prestasi melalui pengoptimuman JOIN dalam MySQL May 11, 2023 am 08:48 AM

Dalam kebanyakan aplikasi web, operasi pangkalan data adalah bahagian yang paling asas dan penting. Sebagai sistem pengurusan pangkalan data hubungan yang paling biasa digunakan pada masa ini, MySQL menjadi tuan rumah laman web dan aplikasi yang tidak terkira banyaknya dan juga menghadapi tekanan yang semakin meningkat pada pemprosesan data dan akses pertanyaan. Dalam konteks ini, pengoptimuman prestasi telah menjadi bahagian penting dalam pengurusan pangkalan data MySQL, dan operasi JOIN adalah perkara utama. Sambungan JOIN ialah salah satu pernyataan pertanyaan data yang paling biasa digunakan dalam MySQL. wujud

Bagaimana untuk mengoptimumkan pernyataan gabungan dalam MySQL Bagaimana untuk mengoptimumkan pernyataan gabungan dalam MySQL Jun 03, 2023 am 09:31 AM

SimpleNested-LoopJoin Mari kita lihat cara mysql berfungsi apabila melaksanakan operasi gabungan. Apakah kaedah gabungan biasa? Seperti yang ditunjukkan dalam rajah, apabila kita melakukan operasi sambungan, jadual di sebelah kiri ialah jadual pemanduan dan jadual di sebelah kanan ialah jadual pemacu SimpleNested-LoopJoin Operasi sambungan ini adalah untuk mengambil rekod daripada jadual pemanduan dan kemudian padankan rekod jadual yang dipandu satu persatu Jika keadaan Jika ada padanan, keputusan dikembalikan. Kemudian rekod seterusnya dalam jadual pemacu diambil untuk pemadanan sehingga semua data dalam jadual pemacu dipadankan Oleh kerana ia memakan masa untuk mendapatkan semula data daripada jadual pemacu setiap kali, MySQL tidak menggunakan algoritma ini untuk melaksanakan operasi sambungan. BlockNested-LoopJ

Tukar tatasusunan kepada rentetan menggunakan fungsi PHP join(). Tukar tatasusunan kepada rentetan menggunakan fungsi PHP join(). Jun 26, 2023 pm 11:18 PM

PHP ialah bahasa skrip sebelah pelayan yang biasa digunakan Ia mempunyai banyak fungsi yang berguna, salah satunya ialah fungsi join(). Ia boleh menukar tatasusunan kepada rentetan Artikel ini akan memperincikan cara menggunakan fungsi PHPjoin() untuk menukar tatasusunan kepada rentetan. 1. Apakah fungsi PHPjoin()? Fungsi join(), juga dikenali sebagai fungsi implode() adalah salah satu kaedah dalam PHP untuk menukar tatasusunan kepada rentetan. Fungsinya adalah untuk menyambung unsur-unsur dalam tatasusunan untuk membentuk rentetan, yang boleh

See all articles