WordPress自定义文章类型实现 .html 静态链接,同时保留页面slug的完美方案

文章目录

在 WordPress 开发中,我们经常会遇到这样的需求:

  • 使用自定义文章类型(CPT)如 case 展示项目或案例;
  • 希望每个内容的访问链接为 /case/123.html/case/my-slug.html,符合静态页面结构;
  • 又希望访问 /case/ 是一个由 Elementor 或 ACF 制作的普通页面(非 archive),可以自由编辑;
  • 而不使用任何插件,如 Permalink Manager Lite 等

本文将一步步带你使用纯代码实现这个需求,避开 WordPress 的伪静态规则限制,打造一个 SEO 友好 + 灵活定制 + 100% 插件无依赖 的解决方案。

📌 最终目标 URL 结构如下

页面类型 示例 URL 实现说明
自定义页面 /case/ 使用 Elementor/ACF 自由编辑
单个文章页面 /case/123.html/case/slug.html 自定义文章类型的单篇页面

❓ 为什么默认 WordPress 无法实现?

WordPress 中若你将 CPT 设置为 slug = case,同时创建一个同名页面 case,会产生路由冲突

  • /case/ 会优先匹配 CPT 的 archive;
  • 页面无法访问,返回 404;
  • permalink 结构也无法使用 .html

即使你关闭了 has_archive,WordPress 的 rewrite 规则仍然会保留 /case/ 作为内部保留路径,仍无法用页面占用。

✅ 分步实现:不使用插件,手动实现目标 URL

第一步:注册自定义文章类型(避免 slug 冲突)

add_action('init', function () {
    register_post_type('case', [
        'label' => '案例',
        'public' => true,
        'has_archive' => false,
        'rewrite' => [
            'slug' => 'case-item', // 避免和页面 slug 冲突
            'with_front' => false
        ],
        'supports' => ['title', 'editor', 'thumbnail'],
    ]);
});

如果你用的是Custom Post Type UI 插件,设置效果如下


 

第二步:自定义单篇文章 permalink 为 .html

add_filter('post_type_link', function ($post_link, $post) {
    if ($post->post_type === 'case') {
        return home_url('/case/' . $post->ID . '.html');
    }
    return $post_link;
}, 10, 2);

第三步:添加 rewrite 规则支持 .html 解析

add_action('init', function () {
    add_rewrite_rule(
        '^case/([0-9]+)\.html$',
        'index.php?post_type=case&p=$matches',
        'top'
    );
});

⚠️ 务必刷新固定链接: 后台 → 设置 → 固定链接 → 保存更改。

第四步:新建页面 /case/ 并自由编辑

此时因为 has_archive 设置为 false,你可以:

  • 在后台新建一个页面,slug 为 case
  • 使用 Elementor 进行布局;
  • 或用 ACF 添加自定义字段;
  • 页面地址即为 /case/,不会和 CPT archive 冲突。

🎯 Bonus:将链接变为 /case/slug.html 而非 /case/ID.html

修改 post_type_link

add_filter('post_type_link', function ($post_link, $post) {
    if ($post->post_type === 'case') {
        return home_url('/case/' . $post->post_name . '.html');
    }
    return $post_link;
}, 10, 2);

添加 rewrite 规则:

add_action('init', function () {
    add_rewrite_rule(
        '^case/([^/]+)\.html$',
        'index.php?case=$matches',
        'top'
    );
});

注册 query var:

add_filter('query_vars', function ($vars) {
    $vars[] = 'case';
    return $vars;
});

转换 slug 到文章对象:

add_action('pre_get_posts', function ($query) {
    if (!is_admin() && $query->is_main_query() && get_query_var('case')) {
        $slug = get_query_var('case');
        $post = get_page_by_path($slug, OBJECT, 'case');
        if ($post) {
            $query->set('p', $post->ID);
            $query->set('post_type', 'case');
            $query->is_single = true;
            $query->is_page = false;
        }
    }
});

📌 整体实现效果回顾

功能点 说明
✅ 支持 .html 后缀 URL 如 /case/123.html/case/my-slug.html
✅ 页面 /case/ 可编辑 Elementor、ACF 自由编辑,无 archive 冲突
✅ 无需插件 不依赖 Permalink Manager、Rewrite 插件等
✅ SEO 友好结构 自定义结构简洁清晰,利于爬虫索引

🛠 延伸建议

  • 使用 single-case.php 模板自定义显示样式;
  • 若要添加分页、taxonomy 分类支持,可在 rewrite 规则中加入更多正则匹配;
  • 若需求复杂,可以进一步封装成模块或插件。

✅ 结语

通过几段简单但灵活的代码,我们成功实现了:

  • 保留 case 页面用于视觉构建与字段展示;
  • 所有案例链接为 .html 静态风格,利于 SEO;
  • 100% 无插件依赖,代码可控、可维护;
  • 不再被 WordPress 的 rewrite 规则限制。

这就是 WordPress 可定制性的魅力所在。希望本文对你有所帮助!如果你也在构建主题或插件,欢迎留言交流。

发表回复

相关文章
主题推荐
还没有账号?

会员注册

成为会员,获得更多专属优惠!

验证码: 加载中... =

已有账号?