WordPress 模板层级:一个 URL 到底加载哪个文件
WordPress 决定加载哪个文件是固定顺序:解析 URL → 条件标签判断页面类型 → 生成一串候选文件名 → 取第一个真实存在的。本文列出文章、页面、分类、标签、搜索、404 六类页面的完整候选链,指出三处最容易搞错的顺序(front-page.php 会让 home.php 失效、后台指定的页面模板优先级最高、tag.php 不继承 category.php),并给出用 template_include 打印实际命中文件的调试法。
改一个 WordPress 站的模板,最常踩的不是 PHP 写错,是「我建了文件,但它没生效」。因为 WordPress 决定加载哪个文件的顺序是固定的,文件存在不等于被用到。这篇把这条顺序写清楚。
一次请求怎么走到模板文件
分四步:解析 URL 得到查询条件 → 用条件标签判断这是哪种页面 → 生成一串候选文件名(按优先级排列)→ 从上往下找第一个真实存在的文件,找到就停。
关键是第三步:候选是一串,不是一个。你建了两个文件,只有一个会被用到,另一个永远不会执行。
常见页面的候选链
- 单篇文章:single-post-{slug}.php → single-post-{id}.php → single-{post_type}.php → single.php → singular.php → index.php
- 独立页面:后台指定的页面模板 → page-{slug}.php → page-{id}.php → page.php → singular.php → index.php
- 分类:category-{slug}.php → category-{id}.php → category.php → archive.php → index.php
- 标签:tag-{slug}.php → tag-{id}.php → tag.php → archive.php → index.php
- 搜索结果:search.php → index.php
- 404:404.php → index.php
规律很清楚:越具体的越靠前,index.php 永远兜底。
三处容易搞错的顺序
一是首页。front-page.php 在「静态首页」和「文章列表首页」两种情况下都会生效,优先级高于 home.php,也高于 page.php。想让文章列表首页走 home.php,就别建 front-page.php——建了它,home.php 直接作废。
二是页面。后台给页面选的「页面模板」优先级最高。只要指定了,page-{slug}.php 和 page-{id}.php 都不会被用。很多人建了 page-about.php 没反应,就是因为后台选着别的模板。
三是标签与分类。tag.php 不继承 category.php,两者是并行的,都没有才落到 archive.php。想让标签页和分类页长得不一样,必须单独建 tag.php,改 category.php 不会连带生效。
调试:它到底用了哪个文件
add_action('template_include', function ($t) {
error_log('template: ' . $t);
return $t;
});
比一个个建文件试快得多,打出来的是绝对路径,一眼能看出命中的是子主题还是父主题。
子主题只覆盖一个文件
把同路径、同名的文件放进子主题目录就行,父主题不用动。WordPress 先查子主题再查父主题,所以自定义时最省事的做法是:改哪页就只放哪页,其余照旧继承。这也是为什么升级父主题不会冲掉你的改动。
页内片段:get_template_part
候选链管的是「整页」,页内的一块用 get_template_part('template-parts/card', 'post')。它同样是先子主题后父主题,但有一点不同:两个都找不到时它静默失败,不报错。这是另一个常见的「为什么这块是空的」的来源。