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
分批处理 - 频繁查询的关联数据考虑缓存