今天我们来聊聊一个能让你的网站瞬间提速 ,且让代码看起来非常高端的技术:ThinkCMF 的关联模型与预加载(Eager Loading)。
在开发中,我们经常遇到"循环查询"的陷阱(也就是著名的 N+1 问题)。比如:你查询了 10 条文章,为了显示每篇文章的作者昵称,代码在循环里又去查了 10 次用户表。这会导致数据库压力剧增。
📅 今日知识点:利用预加载(With)告别性能瓶颈
核心逻辑:
不要在 foreach 循环里去写 Db::name('user')->find()。你应该在查询文章时,告诉模型:"请把这些文章的作者信息一次性带出来。"
1. 错误示范(性能杀手)
php
$articles = Db::name('portal_post')->limit(10)->select();
foreach($articles as &$vo) {
// ❌ 错误:循环内查库,查询了 10 次数据库
$vo['user_nickname'] = Db::name('user')->where('id', $vo['user_id'])->value('user_nickname');
}
2. 正确姿势:使用 with() 预加载
在 ThinkCMF(基于 ThinkPHP 5.1/6.0)中,模型关联是极其强大的。假设你在 PostModel 中已经定义了 user 关联:
php
// 在控制器中
use app\portal\model\PortalPostModel;
$postModel = new PortalPostModel();
// ✅ 正确:使用 with('user'),底层只会执行 2 条 SQL
$articles = $postModel->with(['user'])
->where('post_status', 1)
->limit(10)
->select();
foreach($articles as $vo) {
// 直接访问,无需再次查询数据库
echo $vo->user->user_nickname;
}
3. 进阶:只加载需要的字段
预加载虽好,但如果用户表有 50 个字段,全部查出来也浪费内存。你可以指定字段:
php
$articles = $postModel->with(['user' => function($query) {
$query->field('id, user_nickname, avatar');
}])->select();
💡 为什么这对 ThinkCMF 开发至关重要?
- 减少数据库连接:将 11 次查询缩减为 2 次,在高并发下能保住服务器不宕机。
- 代码整洁:所有的关联逻辑都封装在 Model 里,控制器只负责"下指令"。
- API 友好:如果你在做小程序开发,预加载出的数据可以直接转为 JSON,结构非常清晰。
今日金句: 优秀的 PHP 工程师不只是实现功能,更是数据库的"节约专家"。