12k
All articles

在 WordPress 中创建自定义文章类型

使用register_post_type、show_in_rest、插件式设置以及正确的归档和单页模板创建WordPress自定义文章类型。

OpenReplay Team
OpenReplay Team
在 WordPress 中创建自定义文章类型

WordPress 自带文章(Posts)和页面(Pages),但当客户需要房产列表目录、员工名册或食谱档案时,这两种内容类型就显得力不从心了。这时就需要用到 WordPress 自定义文章类型(Custom Post Type)——一种一流的内容结构,它能够完美融入 WordPress 现有的数据模型,而无需对默认设置进行任何破解性修改。

核心要点

  • 自定义文章类型(CPT)扩展的是共享的 wp_posts 数据表,而不是创建单独的表,这使您可以开箱即用地获得管理界面、REST API 端点和模板路由功能。
  • 始终在插件中注册 CPT,而不是在主题中,这样无论主题如何更改,内容都能保持可访问。
  • 必须将 show_in_rest 设置为 true 才能支持区块编辑器和 REST API 访问。
  • 仅在插件激活时刷新重写规则——切勿在每次页面加载时执行。

什么是自定义文章类型?

自定义文章类型(CPT)是您在 WordPress 中注册的一种命名内容类型。尽管名称如此,但它并不是一个独立的数据库表。所有文章类型——无论是内置的还是自定义的——都共享 wp_posts 表,通过 post_type 列进行区分。这是一个重要的概念模型:您是在扩展现有结构,而不是创建一个平行结构。

默认的文章类型包括 postpageattachmentrevisionnav_menu_item。当您注册一个像 propertyrecipe 这样的 CPT 时,WordPress 会以同样一致的方式对待它:管理界面、REST API 端点、URL 路由和模板层级都以相同的方式工作。

自定义文章类型 ≠ 自定义字段。 CPT 定义的是内容的类型。自定义字段(通过 ACF 或元数据 API 添加)存储的是附加到该内容的额外数据。这是两个不同的概念。

使用 register_post_type() 注册自定义文章类型

创建 WordPress 自定义文章类型的标准方法是使用 register_post_type() 函数,在 init 钩子上调用。

以下是一个简洁且可用的示例:

add_action( 'init', 'register_property_post_type' );

function register_property_post_type() {
    $labels = [
        'name'               => 'Properties',
        'singular_name'      => 'Property',
        'add_new_item'       => 'Add New Property',
        'edit_item'          => 'Edit Property',
        'not_found'          => 'No properties found.',
    ];

    $args = [
        'labels'       => $labels,
        'public'       => true,
        'has_archive'  => true,
        'supports'     => [ 'title', 'editor', 'thumbnail', 'excerpt' ],
        'rewrite'      => [ 'slug' => 'properties' ],
        'show_in_rest' => true,
    ];

    register_post_type( 'property', $args );
}

关键参数说明

  • public — 使 CPT 在管理后台和前端可见。对于仅供内部使用的类型,设置为 false
  • labels — 控制管理后台中的所有 UI 文本。值得正确填写,以免编辑人员感到困惑。
  • supports — 声明编辑界面上显示哪些编辑器功能。常用值:titleeditorthumbnailexcerptcustom-fields
  • has_archive — 在 /properties/ 启用归档页面。WordPress 会查找匹配的 archive-property.php 模板(或回退到 archive.php)。
  • rewrite — 设置 URL 别名。单篇文章将显示在 /properties/post-name/
  • show_in_rest将此设置为 true 这会通过 WordPress REST API 公开 CPT,并且是区块编辑器正确处理您的文章类型所必需的。没有它,编辑器会回退到经典界面。

插件 vs. 主题:代码应该放在哪里?

这是一个常见的困惑点。在插件中注册自定义文章类型,而不是在主题中。

如果您的 CPT 注册代码位于 functions.php 中,而客户切换了主题,该类型的所有内容将变得无法访问——不是被删除,而是不可见。一个专用插件(即使是简单的单文件插件)可以使 CPT 在主题更改时保持活动状态。

不要在每次请求时刷新重写规则。 仅调用一次 flush_rewrite_rules() ——通过 register_activation_hook() 在插件激活时调用。在每次 init 时刷新会导致性能问题。

自定义文章类型的模板层级

对于单个 CPT 条目,WordPress 按以下顺序查找模板:

  1. single-{post-type}.php(例如 single-property.php)
  2. single.php
  3. singular.php
  4. index.php

对于归档页面,遵循:archive-{post-type}.phparchive.phpindex.php

总结

通过将 register_post_type() 正确挂载到 init,启用 show_in_rest,并将注册代码放在插件中,您就有了一个坚实、可移植的基础。从这里开始,您可以添加自定义分类法、通过 ACF 或元数据 API 添加元字段,以及自定义管理列——而不会触及任何在 WordPress 或主题更新时会损坏的内容。

常见问题

如果我停用注册自定义文章类型的插件,我的自定义文章类型内容会怎样?

内容会保留在 wp_posts 表中,不会被删除。但是,WordPress 不再识别该文章类型,因此这些文章在管理后台和前端都会变得不可见。重新激活插件会立即恢复访问。这就是为什么 CPT 注册应该始终位于专用插件中而不是主题中的原因。

我可以在单个插件中注册多个自定义文章类型吗?

可以。您可以在同一个 init 回调中多次调用 register_post_type(),或使用挂载到 init 的单独回调。单个插件可以注册的自定义文章类型数量没有限制,但每个类型必须有一个不超过 20 个字符的唯一文章类型别名。

为什么我的自定义文章类型 URL 返回 404 错误?

这几乎总是意味着需要刷新重写规则。在 WordPress 管理后台访问设置,然后访问固定链接,点击保存更改。这会触发重写刷新。对于插件,在 register_activation_hook() 内调用 flush_rewrite_rules(),这样它会在激活时自动运行。切勿在每次页面加载时刷新。

如果我使用经典编辑器,是否需要将 show_in_rest 设置为 true?

严格来说不需要,但仍然建议这样做。将 show_in_rest 设置为 true 会通过 WordPress REST API 公开您的文章类型,这对于无头设置、外部集成和未来兼容性很有用。如果您将来切换到区块编辑器,它已经可以正常工作了。

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.