最近重新检查 WordPress 首页时,我发现分类下拉列表又出现了一个似曾相识的问题。
在首页右侧的分类下拉列表中选择 PHP Simple HTML DOM Parser 后,浏览器访问的是:
https://www.shuijingwanwq.com/?category_name=php-simple-html-dom-parser
但页面并没有继续进入真正的分类归档,而是仍然显示了首页内容。

category_name 查询参数跳转,而当前页面没有进入对应分类归档。这个现象让我很快想到了之前做过的两次调整:一次是分类下拉列表的多语言域名修复,另一次则是针对 CDN Query String 的缓存优化。
这两个原本各自正常的功能,在后来组合到一起后,产生了新的冲突。
一、这个分类下拉列表,其实以前已经修过一次
2026 年 7 月 13 日,在将 WordPress 英文站迁移到独立子域名之后,我曾经处理过一次分类下拉列表跳转错误。
当时的完整排查过程记录在 《WordPress Polylang 英文子域名迁移后链接仍指向中文站:分类下拉、面包屑与区块模板的完整修复》 中。(水晶湾物业)
发布到 WordPress 时,这类正文链接均设置为“在新标签页中打开”。
当时最明显的问题,是英文首页选择 Browser 分类以后,分类 slug 明明属于英文分类,但跳转 URL 使用的却仍然是中文主域名。文章中最终确认,英文分类数据和正式分类固定链接本身都没有问题,错误主要发生在分类下拉列表生成的跳转地址上。(水晶湾物业)
当时修复完成后的流程仍然是:
选择分类
↓
生成 /?category_name=分类别名
↓
WordPress 解析 category_name
↓
跳转到最终分类固定链接
例如:
https://en.shuijingwanwq.com/?category_name=browser-en
随后再进入:
https://en.shuijingwanwq.com/category/application-tool-en/browser-en/
这套方式当时是可以正常工作的。
二、后来做的 Query String 优化,让这个问题重新暴露出来
到了 2026 年 8 月 3 日,我又针对 WordPress 页面缓存和 CDN Cache Key 做了一次 Query String 归一化优化。
相关过程记录在 《从 EdgeOne 524 到 Query String 归一化:WordPress 文章与公开列表页 CDN 缓存优化实战》 中。
这次优化的核心目标,是避免一些不会改变页面内容的查询参数不断生成新的缓存版本。
例如对于普通公开页面而言:
/
与:
/?random=123
如果最终页面内容完全相同,就没有必要分别维护一份页面缓存。
这个优化方向本身没有问题。
但重新测试分类下拉列表以后,我意识到:
category_name
并不是普通的无意义 Query String。
它承担了 WordPress 分类下拉列表的实际跳转功能。
于是就出现了这样一条冲突链路:
分类下拉列表
↓
生成 ?category_name=slug
↓
CDN Query String 归一化
↓
category_name 没有继续按照原来的方式影响请求
↓
WordPress 得到的效果接近普通首页
最初很容易想到的修复方式,是继续修改 EdgeOne 或 Cloudflare 规则,把:
category_name
也加入需要保护的功能性 Query String。
但再往前想一步,我发现还有一个更简单的问题:
为什么分类下拉列表一定要先经过 ?category_name=?
三、既然已经知道最终地址,为什么不直接跳过去?
WordPress 分类真正需要访问的其实是标准分类固定链接。
例如 PHP Simple HTML DOM Parser 的最终地址是类似:
/category/web-devel/html-parser/php-simple-html-dom-parser/
那么现在的链路:
选择分类
↓
/?category_name=slug
↓
WordPress 再解析
↓
最终分类地址
完全可以简化成:
选择分类
↓
最终分类地址
这样带来的好处很直接。
第一,少了一层中间请求。
第二,分类下拉列表不再依赖 Query String。
第三,它与 CDN 的 Query String 缓存规则彻底解耦。
第四,分类归档本来就是标准固定链接形式,后续缓存策略也更加直观。
不过这里不能简单地按照 slug 自己拼:
/category/php-simple-html-dom-parser/
因为我的 WordPress 分类存在父子层级。
真正地址可能是:
/category/web-devel/html-parser/php-simple-html-dom-parser/
所以最终 URL 仍然应该由 WordPress 自己生成,而不是在 JavaScript 中猜测路径。
四、继续使用 WPCode,不修改 Twenty Twenty-Five
这次我仍然选择使用 WPCode 完成调整,而不是直接修改 Twenty Twenty-Five 主题文件。
原来的代码片段名称是:
修复非默认语言站分类下拉列表跳转域名
它的职责主要是解决 7 月 13 日发现的英文站跳回中文主域名问题。
现在功能已经发生变化,因此我将它改名为:
分类下拉列表直接跳转最终分类链接
没有重新创建第二份代码片段,而是直接修改原来的代码。
这样可以避免两份 JavaScript 同时监听同一个分类下拉列表。

五、页面范围尽量交给 WPCode,而不是继续堆 PHP 判断
这次调整时,我也继续采用最近比较喜欢的 WPCode 使用方式:
能通过 Location 与 Smart Conditional Logic 完成的页面判断,就不要再重复写进 PHP。
代码片段使用:
Code Type:
PHP Snippet
Insert Method:
Auto Insert
Location:
Frontend Conditional Logic
最开始我考虑只限制在 Homepage。
但实际检查后发现,分类下拉列表不仅存在于首页,在分类等归档页面中同样存在。
因此最终配置为:
Type of Page → Is → Homepage
OR
Type of Page → Is → Archive

这样一来,PHP 代码中就没有必要重复维护类似:
is_front_page()
is_home()
is_archive()
is_admin()
这样的页面条件。
WPCode 负责回答:
哪些页面需要执行?
PHP 代码只负责回答:
分类下拉列表应该怎样直接跳到最终 URL?
职责会清晰很多。
六、最终代码
最终使用的 WPCode 代码如下:
/**
* SWQ:分类下拉列表直接跳转最终分类链接。
*/
add_filter(
'render_block_core/categories',
function ( $block_content, $block ) {
if ( empty( $block['attrs']['displayAsDropdown'] ) ) {
return $block_content;
}
$processor = new WP_HTML_Tag_Processor( $block_content );
while ( $processor->next_tag( 'option' ) ) {
$slug = $processor->get_attribute( 'value' );
if ( empty( $slug ) || '-1' === $slug ) {
continue;
}
$term = get_term_by( 'slug', $slug, 'category' );
if ( ! $term || is_wp_error( $term ) ) {
continue;
}
$url = get_term_link( $term );
if ( is_wp_error( $url ) ) {
continue;
}
$processor->set_attribute(
'data-swq-term-url',
$url
);
}
$block_content = $processor->get_updated_html();
static $script_added = false;
if ( ! $script_added ) {
$script_added = true;
$block_content .= <<<'HTML'
<script>
document.addEventListener('change', function (event) {
const dropdown = event.target;
if (!(dropdown instanceof HTMLSelectElement)) {
return;
}
const option = dropdown.options[dropdown.selectedIndex];
const url = option?.dataset.swqTermUrl;
if (!url) {
return;
}
event.stopPropagation();
window.location.assign(url);
}, true);
</script>
HTML;
}
return $block_content;
},
20,
2
);
这里并没有粗暴地把 <option> 原来的 value 从 slug 修改成 URL。
原来的结构仍然保留,例如:
<option value="php-simple-html-dom-parser">
只是在渲染时额外增加最终分类 URL,大致类似:
<option
value="php-simple-html-dom-parser"
data-swq-term-url="https://www.shuijingwanwq.com/category/web-devel/html-parser/php-simple-html-dom-parser/"
>
当用户重新选择分类时,JavaScript 读取:
data-swq-term-url
然后:
window.location.assign(url);
直接进入最终地址。
最重要的是,最终 URL 来自:
get_term_link()
而不是自己拼接。
这样父子分类结构、分类 slug,以及中文站和英文站各自的域名,都继续交给 WordPress 和现有多语言体系处理。
七、这次没有急着清缓存
修改 WPCode 后,我没有马上清理所有页面缓存和 CDN 缓存。
因为旧页面已经存在缓存,如果马上手工清除所有缓存,很难观察自然缓存生命周期之后实际访客得到的结果。
因此这一次直接等待缓存自然过期。
从 8 月 8 日完成修改,到 8 月 14 日再次检查,中间没有因为测试结果焦虑而继续修改代码。
几天后再测试,看到的已经是自然更新后的页面。
八、8 月 14 日进行四组实际验证
缓存自然过期以后,我重新测试了四种场景:
- 中文首页 → 选择一个分类
- 中文归档页 → 选择一个分类
- 英文首页 → 选择一个分类
- 英文归档页 → 选择一个分类
四项全部通过。
现在正常操作分类下拉列表时,浏览器已经不需要再经过:
/?category_name=xxx
而是直接进入最终分类固定链接。
例如在中文归档页面选择 Bootstrap 5 后,浏览器直接进入:
https://www.shuijingwanwq.com/category/web/html-css/css-framework/bootstrap/bootstrap-5/

category_name 中转地址。这正是这次修改最核心的验证结果。
九、最终没有为了它修改 EdgeOne 和 Cloudflare
发现问题之初,还有一种完全可以实施的方案:
保留 ?category_name=
+
在 CDN 中把 category_name 加入功能性 Query String 例外
但最终我没有这样做。
原因也很简单。
新的分类下拉逻辑生效以后,正常用户已经不会再通过:
/?category_name=xxx
访问分类。
既然业务链路已经不需要这个中间查询参数,自然没有必要再让 EdgeOne 和 Cloudflare 专门为它增加一套例外。
最终两层职责变成:
CDN
↓
继续负责现有 Query String 归一化与页面缓存
WordPress 分类下拉列表
↓
直接访问标准分类固定链接
两者不再互相依赖。
这比继续不断扩大 Query String 白名单要简单得多。
十、这次真正解决的,不只是一个跳转错误
一开始看到:
/?category_name=php-simple-html-dom-parser
失效时,我最先想到的仍然是:
再给 CDN 加一个例外。
这是面对兼容问题时非常自然的思路。
但这次最后的解决方式让我觉得更值得记录:
与其不断给后来增加的规则补例外,不如先看看旧业务链路里有没有本来就可以删除的中间层。
原来的结构:
分类下拉列表
↓
category_name
↓
WordPress 查询参数解析
↓
最终分类固定链接
现在变成:
分类下拉列表
↓
最终分类固定链接
少了 Query String,少了一次中转,也少了一层和 CDN 的耦合。
同时,这次也进一步确定了我现在使用 WPCode 时比较倾向的一种方式:
Location / Enable Logic
↓
负责“在哪里运行”
PHP / JavaScript
↓
只负责“运行什么”
能交给配置界面的页面判断,就尽量不再塞进代码。
这样不仅代码更精简,以后几个月甚至几年后重新查看这个代码片段时,也更容易快速理解它的职责。
总结
这次 WordPress 分类下拉列表问题,最开始看起来只是 Query String 缓存策略带来的一个兼容性回归。
但最终并没有通过增加:
category_name
缓存例外来修复。
而是把整个分类跳转链路进一步简化为:
WPCode
+
render_block_core/categories
+
WP_HTML_Tag_Processor
+
get_term_link()
+
JavaScript 直接跳转最终 URL
代码片段则通过 WPCode 限定在:
Homepage OR Archive
等待缓存自然过期后,中文首页、中文归档页、英文首页、英文归档页四种场景全部验证通过。
至此,正常的分类下拉列表访问已经不再依赖:
?category_name=
而是一步进入最终 /category/.../ 固定链接。
这次优化看起来只是少掉一个 Query String,但真正减少的是业务跳转逻辑与 CDN 缓存规则之间不必要的耦合。
WordPress 网站维护、性能优化与博客运营咨询
本站已持续运营超过 10 年,累计发布 1000+ 篇原创技术文章,长期实践 WordPress 网站建设、CDN / Cloudflare 配置、缓存优化、Google SEO、广告变现和多语言网站运营。
如果你的 WordPress 网站遇到访问慢、缓存异常、插件冲突、广告不显示、SEO 基础结构混乱、CDN 配置不确定等问题,可以联系我做一次远程技术排查。
适合以下用户:
✅ 个人博客站长
✅ WordPress 网站运营者
✅ 独立开发者与内容创作者
✅ SaaS 产品官网运营团队
✅ 希望优化网站速度与稳定性的站点
服务内容:
✅ WordPress 速度优化
✅ Cloudflare / CDN / 缓存配置排查
✅ 插件冲突与页面异常排查
✅ AdSense 广告显示问题排查
✅ SEO 基础结构检查
✅ 博客运营与商业化咨询
如需了解方案或交流相关问题,请直接联系我,并注明:WordPress 维护咨询。
联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com


发表回复