ThinkPHP6模型关联实战:5种高级关联用法详解
1. 一对多关联的嵌套预加载
处理多层关联关系时,使用嵌套预加载可以显著减少查询次数:
// 用户模型
class User extends Model
{
public function articles()
{
return $this->hasMany(Article::class);
}
}
// 文章模型
class Article extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
// 控制器中一次性获取用户及其所有文章和评论
$users = User::with(['articles' => ['comments']])->select();
2. 多态关联实现通用评论系统
多态关联允许一个模型关联到多个其他模型:
// 评论模型
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
// 文章模型
class Article extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
// 视频模型
class Video extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
// 添加评论到不同模型
$article->comments()->save($comment);
$video->comments()->save($comment);
3. 关联统计的进阶用法
使用withCount进行关联统计并添加条件:
// 获取用户及其文章数量(只统计已发布的)
$users = User::withCount([
'articles' => function($query) {
$query->where('status', 1);
}
])->select();
// 获取热门标签(按使用次数排序)
$tags = Tag::withCount('articles')->order('articles_count', 'desc')->limit(10)->select();
4. 远程一对多关联实现跨模型查询
通过中间模型关联远端模型:
// 国家模型
class Country extends Model
{
public function users()
{
return $this->hasMany(User::class);
}
public function posts()
{
return $this->hasManyThrough(Post::class, User::class);
}
}
// 获取某国家的所有文章
$country = Country::find(1);
$posts = $country->posts()->select();
5. 动态关联条件与排序
在运行时动态设置关联条件和排序:
// 获取用户及其最近3篇文章
$user = User::with([
'articles' => function($query) {
$query->where('status', 1)
->order('create_time', 'desc')
->limit(3);
}
])->find(1);
// 动态关联条件
$status = input('status');
$user->articles()->where('status', $status)->select();
- 合理使用with预加载避免N+1查询问题
- 大数据集考虑使用chunk分批处理
- 频繁使用的关联可以定义在模型基类中
掌握这些ThinkPHP6模型关联的高级技巧,可以大幅提升开发效率和代码质量,构建更加健壮的后端系统。