本文详解如何在WordPress中创建和管理自定义文章类型(Custom Post Type),扩展网站内容模型。

什么是自定义文章类型(CPT)

默认WordPress只有"文章(post)"和"页面(page)"。CPT允许你创建:
- 产品(Product) → 电商网站
- 案例(Portfolio) → 作品展示
- 课程(Course) → 在线教育
- 活动(Event) → 活动报名

基础:注册自定义文章类型

方式一:使用代码(推荐)

// functions.php 或自定义插件
add_action('init', 'register_product_cpt');

function register_product_cpt() {
    $args = [
        'labels' => [
            'name'          => '产品',
            'singular_name' => '产品',
            'add_new'      => '添加产品',
            'edit_item'    => '编辑产品',
            'all_items'    => '所有产品',
        ],
        'public'       => true,
        'show_in_rest' => true,  // 暴露给REST API(必须!)
        'menu_icon'    => 'dashicons-cart',
        'supports'     => ['title', 'editor', 'thumbnail', 'excerpt'],
        'rewrite'      => ['slug' => 'product'],
        'has_archive'  => true,
    ];

    register_post_type('product', $args);
}

关键参数详解

参数 作用 推荐值
public 前台可见 true
show_in_rest 暴露给REST API true(必须)
supports 支持的编辑功能 ['title','editor','thumbnail']
rewrite URL重写规则 ['slug'=>'product']
has_archive 启用归档页 true
menu_icon 后台菜单图标 dashicons-*

为CPT添加自定义分类法(Taxonomy)

add_action('init', 'register_product_taxonomy');

function register_product_taxonomy() {
    register_taxonomy('product_cat', 'product', [
        'labels' => [
            'name' => '产品分类',
            'singular_name' => '产品分类',
        ],
        'public'       => true,
        'show_in_rest' => true,  // 暴露给Gutenberg编辑器
        'hierarchical' => true,   // 像分类目录(false则像标签)
        'rewrite'      => ['slug' => 'product-category'],
    ]);
}

在REST API中暴露CPT

默认行为

show_in_rest = true  →  自动注册到 /wp/v2/product
GET  /wp/v2/product          → 列表
POST /wp/v2/product          → 创建
GET  /wp/v2/product/{id}    → 单个

自定义REST API字段

add_action('rest_api_init', 'add_product_price_field');

function add_product_price_field() {
    register_rest_field('product', 'price', [
        'get_callback' => function($post) {
            return get_post_meta($post['id'], '_price', true);
        },
        'update_callback' => function($value, $post) {
            update_post_meta($post->ID, '_price', $value);
        },
        'schema' => [
            'type' => 'number',
        ],
    ]);
}

现在API返回:

GET /wp/v2/product/123
{
  "id": 123,
  "title": {"rendered": "My Product"},
  "price": 299,
  "acf": {...}
}

在Gutenberg编辑器中集成CPT

注册自定义区块(Block)

// block.json
{
  "name": "my-plugin/product-card",
  "title": "产品卡片",
  "category": "widgets",
  "supports": {"html": false}
}
// edit.js (Gutenberg编辑器组件)
import { useSelect } from '@wordpress/data';

function Edit() {
  const products = useSelect((select) =>
    select('core').getEntityRecords('postType', 'product', { per_page: 10 })
  );

  return (
    <div>
      {products && products.map(p => (
        <div key={p.id}>
          <h3>{p.title.rendered}</h3>
          <p>{p.excerpt.rendered}</p>
        </div>
      ))}
    </div>
  );
}

使用高级自定义字段(ACF)扩展CPT

创建产品字段组

ACF后台设置:
- 字段组标题:产品信息
- 位置:Post Type == product
- 字段:
  1. 价格(price) → 数字类型
  2. SKU(sku) → 文本类型
  3. 库存状态(stock_status) → 选择类型(有货/缺货)

在主题中调用ACF字段

// single-product.php
get_header();

$price = get_field('price');
$sku   = get_field('sku');

echo '<h1>' . get_the_title() . '</h1>';
echo '<p>价格:¥' . $price . '</p>';
echo '<p>SKU:' . $sku . '</p>';

get_footer();

CPT的URL重写与SEO

自定义固定链接结构

// 产品URL:/product/{sku}/{post_name}/
add_filter('post_type_link', 'product_permalink', 10, 2);

function product_permalink($post_link, $post) {
    if ('product' === $post->post_type) {
        $sku = get_field('sku', $post->ID);
        return str_replace('%sku%', $sku, $post_link);
    }
    return $post_link;
}

// 注册时:
'rewrite' => ['slug' => 'product/%sku%'],

提交CPT到Google Search Console

<!-- 在 sitemap.xml 中添加 CPT -->
<url>
  <loc>https://example.com/product/my-awesome-product</loc>
  <lastmod>2026-05-01T12:00:00+08:00</lastmod>
  <changefreq>weekly</changefreq>
  <priority>0.8</priority>
</url>

实战:创建"课程(Course)" CPT

完整代码示例

// 注册Course CPT
add_action('init', function() {
    register_post_type('course', [
        'labels' => [
            'name' => '课程',
            'singular_name' => '课程',
        ],
        'public'       => true,
        'show_in_rest' => true,
        'supports'     => ['title', 'editor', 'thumbnail', 'excerpt'],
        'menu_icon'    => 'dashicons-welcome-learn-more',
        'rewrite'      => ['slug' => 'course'],
        'has_archive'  => true,
        'show_in_graph' => true,  // 支持Schema.org
    ]);
});

// 添加"难度"分类法
add_action('init', function() {
    register_taxonomy('course_difficulty', 'course', [
        'labels' => ['name' => '难度'],
        'hierarchical' => true,
        'show_in_rest' => true,
    ]);
});

在主题中显示课程列表

// archive-course.php
get_header();

$query = new WP_Query([
    'post_type' => 'course',
    'posts_per_page' => 12,
    'tax_query' => [[
        'taxonomy' => 'course_difficulty',
        'field'    => 'slug',
        'terms'    => 'beginner',
    ]],
]);

while ($query->have_posts()) {
    $query->the_post();
    echo '<h2><a href="' . get_permalink() . '">' . get_the_title() . '</a></h2>';
    the_excerpt();
}

get_footer();

2026年CPT开发趋势

趋势一:CPT + Headless WordPress

// Next.js 获取 CPT 数据
async function getCourses() {
  const res = await fetch('https://example.com/wp-json/wp/v2/course');
  return res.json();
}

// 现在你可以在Next.js中渲染课程列表
export default async function CoursesPage() {
  const courses = await getCourses();
  return (
    <div>
      {courses.map(c => <div key={c.id}>{c.title.rendered}</div>)}
    </div>
  );
}

趋势二:CPT + Schema.org结构化数据

// 自动添加Schema.org标记
add_action('wp_head', 'add_course_schema');

function add_course_schema() {
    if ('course' !== get_post_type()) return;

    $schema = [
        '@context' => 'https://schema.org',
        '@type'    => 'Course',
        'name'     => get_the_title(),
        'description' => get_the_excerpt(),
    ];

    echo '<script type="application/ld+json">' . json_encode($schema) . '</script>';
}

趋势三:使用插件生成CPT(无代码)

推荐插件:
1. Custom Post Type UI(免费,界面化创建CPT)
2. Pods Framework(免费,支持高级关系)
3. Toolset Types(付费,全功能)

性能优化

问题:CPT查询慢

-- 未优化查询
SELECT * FROM wp_posts WHERE post_type='product' ORDER BY post_date DESC;

-- 优化:添加索引
CREATE INDEX idx_post_type_date ON wp_posts (post_type, post_date);

使用Transient API缓存CPT查询

$courses = get_transient('featured_courses');

if (false === $courses) {
    $courses = new WP_Query([
        'post_type' => 'course',
        'posts_per_page' => 5,
        'meta_key' => '_is_featured',
        'meta_value' => '1',
    ]);

    set_transient('featured_courses', $courses, 12 * HOUR_IN_SECONDS);
}

决策建议

  • 简单网站 → 使用Custom Post Type UI插件
  • 复杂关系(课程→讲师→学生)→ 使用Pods Framework
  • Headless WordPress → 代码注册 + show_in_rest=true
  • 电商网站 → 直接用WooCommerce(不要自己写Product CPT)

总结

CPT是WordPress从"博客工具"进化为"CMS"的关键功能。2026年,CPT + REST API + Headless前端是主流架构。

立即行动:在你的下一个项目中,尝试用CPT创建"产品"或"案例"类型,体验WordPress的真正威力。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。