首页控制器中需在Index::index()方法内用Db::name('category')->where('status',1)->order('sort','asc')->select()查询分类,再通过$this->assign('categories',$categories)传给模板,模板中用{volist name="categories" id="cat"}循环输出。

首页控制器里怎么查分类数据
ThinkPHP6.1 的首页默认走 app\controller\Index::index(),想在首页显示商品分类,就得在这个方法里查出来,再传给模板。别指望模板里直接用 Db::table() —— 模板层不建议写查询逻辑,也容易出作用域问题。
常见错误是直接在模板里用 Db::name('category')->select(),结果报错 Class 'Db' not found 或渲染为空——因为模板里没自动加载数据库类,且 TP6 默认关闭了模板中使用助手函数的权限。
- 在
app\controller\Index.php的index()方法里加查询:$categories = Db::name('category')->where('status', 1)->order('sort', 'asc')->select(); - 确保表名和字段名匹配你的真实数据结构(比如状态字段可能是
is_show、排序字段可能是list_order) - 用
$this->assign('categories', $categories)传给模板,不是return view(...)里塞数组
模板里怎么安全输出分类列表
TP6.1 默认开启模板引擎的安全输出,{$categories} 会直接打印数组字符串,不是你想要的循环列表。必须用 {volist} 标签,且注意键名要和控制器传入的一致。
容易踩的坑:用了 {foreach} 却没开 template.engine.type 配置为 think(默认就是,但改过配置的人常忽略);或者把变量名写成 {$cate},但控制器 assign 的是 categories。
立即学习“PHP免费学习笔记(深入)”;
- 模板路径一般是
view/index/index.html - 正确写法:
{volist name="categories" id="cat"}<a href="{:url('goods/list', ['cat_id'=>$cat['id']])}">{$cat.name}</a>{/volist} - 如果分类有层级(如一级/二级),不要在模板里递归调用
{volist},先在控制器里用buildTree()处理好,再传过去
为什么首页分类加载慢或不更新
TP6.1 默认没开模板缓存,但如果你开启了(template.cache_enable = true),修改了分类数据后,首页仍显示旧内容——因为 volist 渲染结果被缓存了,但数据源没变。
更隐蔽的问题是:分类表没加索引,where status=1 order by sort 在几千条数据时可能拖慢首页 TTFB。
- 检查
config/template.php中cache_expire是否设为0(开发期推荐) - 给分类表的
status和sort字段建联合索引:ALTER TABLE `category` ADD INDEX `idx_status_sort` (`status`, `sort`); - 如果分类极少变动,可以用
Cache::get('home_categories')+ 定时命令刷新,避免每次首页都查库
要不要在中间件里预加载分类
没必要。首页是具体路由(如 /),不是全局入口;中间件里做查询反而增加所有请求的开销,包括 API 接口、后台页面等。TP6 的请求生命周期里,控制器才是数据准备的合理位置。
真有跨多页面共用分类的需求(比如顶部导航+首页+商品页都要),可以封装成服务类:app\common\service\CategoryService::getListForHome(),然后在各控制器里调用它,而不是扔到中间件里硬塞。
另外,别在 BaseController 的 initialize() 里查分类——首页需要,但登录页、404 页根本用不到,纯属浪费。



















