Custom Post Type (CPT) 讓 WordPress 不只管理文章與頁面,也能管理課程、作品、商品、活動、師資等自訂內容。本章介紹 CPT 的適用情境與外掛實作方式。

本章學習目標

能判斷何時需要 Custom Post Type,並使用外掛註冊自訂內容類型與基本前台顯示。

14.1 自定義貼文類型應用之外掛介紹

如果某類資料有自己的欄位、列表、分類或網址結構,就適合使用 CPT。例如「課程」可能有授課教師、週次、難度與教材連結,與一般文章不同。

CPT 與分類法

CPT 定義內容類型,Taxonomy 定義分類方式。例如 course 是內容類型,而「難度」、「主題」、「學期」可以是分類法。

什麼時候不需要 CPT

不是所有資料都需要 CPT。如果只是一般教學文章,用分類與標籤即可;如果只是頁面中的一段固定內容,也不需要建立新的內容類型。CPT 適合「有一批同類型資料,需要獨立管理、查詢與呈現」的情境。

  • 適合 CPT:課程、商品、作品、活動、師資、出版品。
  • 不一定需要 CPT:網站簡介、單一聯絡資訊、首頁區塊文案。

CPT、欄位與分類的分工

設計資料模型時,可以用三個問題拆解:

  1. 這是什麼種類的內容?如果答案是「課程」,它可能是 CPT。
  2. 它需要哪些屬性?例如教師、週次、時數,這些可能是 meta fields。
  3. 它如何被分組?例如難度、主題、學期,這些可能是 taxonomy。

14.2 在外掛中建立 Custom Post Type

add_action('init', 'wp2026_register_course_cpt');
function wp2026_register_course_cpt() {
    register_post_type('course', [
        'labels' => [
            'name' => '課程',
            'singular_name' => '課程',
        ],
        'public' => true,
        'has_archive' => true,
        'menu_icon' => 'dashicons-welcome-learn-more',
        'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
        'show_in_rest' => true,
    ]);
}

重要參數說明

  • public:是否可在前台查詢與顯示。
  • has_archive:是否有封存列表頁。
  • rewrite:設定網址 slug。
  • supports:後台編輯器支援哪些功能。
  • show_in_rest:是否支援區塊編輯器與 REST API。
  • menu_icon:後台選單圖示。
'rewrite' => ['slug' => 'courses'],
'supports' => ['title', 'editor', 'thumbnail', 'excerpt', 'custom-fields'],

網址與重新整理固定網址

新增 CPT 後若前台出現 404,通常需要到「設定 → 固定網址」按儲存,讓 WordPress 重新產生 rewrite rules。

正式外掛可在啟用時呼叫 flush_rewrite_rules(),但不要在每次頁面載入時呼叫,否則會影響效能。

register_activation_hook(__FILE__, 'wp2026_activate');
function wp2026_activate() {
    wp2026_register_course_cpt();
    flush_rewrite_rules();
}

註冊自訂分類法

以下範例替課程建立「課程難度」分類法:

add_action('init', 'wp2026_register_course_taxonomy');
function wp2026_register_course_taxonomy() {
    register_taxonomy('course_level', ['course'], [
        'labels' => ['name' => '課程難度'],
        'public' => true,
        'hierarchical' => true,
        'show_in_rest' => true,
        'rewrite' => ['slug' => 'course-level'],
    ]);
}

新增課程自訂欄位

課程常需要教師、時數、教材網址等欄位。可以先用 meta box 實作,理解資料儲存流程。

add_action('add_meta_boxes', 'wp2026_add_course_meta_box');
function wp2026_add_course_meta_box() {
    add_meta_box(
        'wp2026_course_info',
        '課程資訊',
        'wp2026_render_course_meta_box',
        'course'
    );
}
function wp2026_save_course_meta($post_id) {
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }
    $hours = isset($_POST['wp2026_hours']) ? absint($_POST['wp2026_hours']) : 0;
    update_post_meta($post_id, '_wp2026_hours', $hours);
}
add_action('save_post_course', 'wp2026_save_course_meta');

模板檔案

若 CPT 名稱是 course,可在主題中建立 archive-course.phpsingle-course.php 控制列表與單篇頁面。

// archive-course.php 中可使用一般 Loop
if (have_posts()) {
    while (have_posts()) {
        the_post();
        the_title('<h2>', '</h2>');
        the_excerpt();
    }
}

REST API 與區塊編輯器

show_in_rest 設為 true 後,CPT 才能完整支援區塊編輯器,也能透過 REST API 存取。若未來要做前後端分離或自訂區塊,這個設定很重要。

本章練習

  1. 建立 course CPT。
  2. 新增三筆課程資料。
  3. 建立課程封存頁模板。
  4. 加入一個課程分類法,例如「難度」。