ThinkPHP6模型关联查询的5种高效用法详解
一、关联查询基础概念
ThinkPHP6的ORM提供了强大的关联查询功能,本文将通过商品系统案例演示5种核心用法:
- 一对一关联(hasOne)
- 一对多关联(hasMany)
- 多对多关联(belongsToMany)
- 关联预加载(with)
- 关联统计(withCount)
二、实战案例:电商商品系统
1. 数据库设计
# 商品表 CREATE TABLE `product` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, `price` decimal(10,2) NOT NULL, PRIMARY KEY (`id`) ); # 商品详情表(一对一) CREATE TABLE `product_detail` ( `product_id` int(11) NOT NULL, `description` text, `specs` json DEFAULT NULL ); # 商品评论表(一对多) CREATE TABLE `comment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `product_id` int(11) NOT NULL, `content` text NOT NULL, `create_time` datetime NOT NULL ); # 商品标签中间表(多对多) CREATE TABLE `product_tag` ( `product_id` int(11) NOT NULL, `tag_id` int(11) NOT NULL );
2. 模型关联定义
// Product模型
class Product extends Model
{
// 关联商品详情(一对一)
public function detail()
{
return $this->hasOne(ProductDetail::class);
}
// 关联评论(一对多)
public function comments()
{
return $this->hasMany(Comment::class)->order('create_time DESC');
}
// 关联标签(多对多)
public function tags()
{
return $this->belongsToMany(Tag::class, 'product_tag');
}
}
3. 五种查询实战
用法1:基础关联查询
// 获取商品及其详情
$product = Product::with('detail')->find(1);
echo $product->name;
echo $product->detail->description;
用法2:关联条件过滤
// 只查询有5星好评的商品
$products = Product::has('comments', '>=', 3)
->with(['comments' => function($query){
$query->where('rating', 5)->limit(3);
}])
->select();
用法3:多对多关联操作
// 为商品添加标签 $product = Product::find(1); $product->tags()->attach([1, 2, 3]); // 同步标签(自动处理差异) $product->tags()->sync([2, 4]);
用法4:关联预加载优化
// 避免N+1查询问题
$products = Product::with(['comments', 'tags'])
->limit(10)
->select();
用法5:关联统计查询
// 获取商品及评论数
$products = Product::withCount('comments')
->order('comments_count', 'desc')
->select();
三、性能优化建议
- 使用
with预加载避免N+1查询 - 关联查询时指定字段:
with(['comments'=>function($q){ $q->field('id,content'); }]) - 大数据量时使用
chunk分批处理 - 频繁查询的关联数据考虑缓存

