WordPress 只能寫文章?解鎖 CPT 終極指南,打造獨一無二的網站結構!
嗨,我是浪花科技的 Eric。身為一個天天跟 WordPress 打交道的工程師,我最常被問到的問題之一就是:「Eric,我的網站不只是要發文章,還想放『作品集』、『課程列表』、『房地產物件』,但用內建的『文章』或『頁面』來做,後台都亂成一團,怎麼辦?」
每次聽到這個問題,我心裡都會默默 OS:「朋友,你該認識一下 WordPress 的精髓 —— Custom Post Type (CPT) 了!」很多人以為 WordPress 就只是個部落格系統,只能發文、建頁面,這真是天大的誤會。其實,WordPress 是一個極具彈性的內容管理系統 (CMS),而 CPT 就是解放它真正潛能的那把鑰匙。
今天,就讓我這個有點囉嗦的工程師,帶你從零開始,深入淺出地搞懂什麼是自訂文章類型 (CPT),為什麼你需要它,以及最重要的——如何親手打造一個屬於你自己網站的 CPT。別再把所有東西都塞在「文章」裡了,讓我們一起把 WordPress 後台變得更專業、更有條理吧!
一、CPT 是什麼?為什麼你不用「文章」就好了?
我們先來打個比方。想像一下你的 WordPress 後台是一個大書櫃。內建的「文章 (Posts)」就像是雜誌區,適合放有時效性、可被分類歸檔的內容;「頁面 (Pages)」就像是參考書區,適合放「關於我們」、「聯絡方式」這種比較獨立、靜態的資訊。
那如果今天你想新增一個「電影評論」區呢?每部電影都有導演、演員、上映年份、評分…這些固定的欄位。如果你用「文章」來寫,你可能得每次手動輸入這些資訊,而且它會跟你的部落格文章混在一起,管理起來簡直是場災難。
這時候,CPT 就登場了!
CPT 的核心價值:內容分離與結構化
Custom Post Type,中文叫「自訂文章類型」,它的作用就是在「文章」和「頁面」之外,幫你建立一個全新的、獨立的內容類型。以上面的電影評論為例,我們可以建立一個叫做「電影 (Movies)」的 CPT。
- 內容分離: 在後台,你會看到一個獨立的「電影」選單,跟你原本的「文章」完全分開,井水不犯河水。
- 結構化資料: 你可以為「電影」這個 CPT 加上專屬的分類(例如「電影類型」:科幻、愛情、恐怖)和標籤,甚至搭配 ACF (Advanced Custom Fields) 外掛,新增「導演」、「評分」等專屬欄位。
- 專屬網址結構: 你的電影評論網址可以變成 `yourwebsite.com/movies/interstellar/`,而不是 `yourwebsite.com/interstellar/`,對 SEO 和使用者體驗都更加友善。
- 專屬版面設計: 你可以為所有電影評論設計一個統一的頁面模板 (`single-movies.php`),讓每部電影的介紹頁面風格一致。
簡單來說,CPT 就是幫你把特定類型的內容「規格化」、「模組化」,讓管理和呈現都變得輕而易舉。這也是 WordPress 能從一個部落格系統,進化成能打造任何類型網站的強大 CMS 的關鍵。
二、建立 CPT 的兩種途徑:外掛 vs. 純程式碼
好了,理論講完了,該來點實際的了。建立 CPT 主要有兩種方法,各有優劣,身為工程師,我當然有我的偏好,但還是客觀分析給你聽。
方法一:使用外掛 (例如 CPT UI) – 新手友善的捷徑
對於不想碰程式碼的朋友來說,使用像 Custom Post Type UI (CPT UI) 這類外掛是最快的方法。安裝啟用後,你只需要在圖形化介面填填表格,就能快速建立 CPT 和它的分類 (Custom Taxonomies)。
- 優點: 快速、直覺、零程式碼基礎也能上手。
- 缺點: 網站多了一個外掛,就多了一份效能負擔和潛在的更新、衝突風險。而且如果外掛停用,你建立的 CPT 就會直接消失(內容還在資料庫,但後台和前台都看不到了),有被「綁架」的感覺。
方法二:手刻程式碼 – 工程師的浪漫與堅持
這才是我們今天的主菜!直接在你的佈景主題 `functions.php` 或是自訂外掛中,使用 WordPress 內建的 `register_post_type()` 函式來註冊 CPT。這聽起來很嚇人,但相信我,一旦你搞懂了,你會愛上這種完全掌控的感覺。
- 優點: 效能最佳、穩定性高、完全客製化,所有設定都掌握在自己手裡,不會被任何外掛綁架。
- 缺點: 需要一點點 PHP 基礎,寫錯了可能會讓網站出現白畫面(別怕,我會教你怎麼安全地做)。
身為一個有格調的開發者,我們當然要選第二條路。走,我們來寫 Code!
三、實戰教學:用程式碼打造你的第一個 CPT
我們來建立一個「專案作品 (Projects)」的 CPT,讓設計公司或工作室可以在網站上展示他們的作品。
Step 1: 程式碼要放哪裡?
這是一個非常重要的問題!很多人會直覺地把程式碼丟到當前啟用佈景主題的 `functions.php` 檔案裡。但這不是最好的做法! 因為一旦你更新佈景主題,你寫的程式碼就會被覆蓋掉,消失得無影無蹤。
你有兩個更好的選擇:
- 使用子佈景主題 (Child Theme): 這是 WordPress 官方推薦的方式。在子佈景主題的 `functions.php` 裡新增程式碼,這樣即使主佈景主題更新,你的客製化程式碼也能安然無恙。
- 建立一個專屬的功能性外掛 (Site-specific Plugin): 這是我個人最推薦的方式,也更專業。把所有跟網站功能相關的程式碼(例如註冊 CPT)都打包成一個外掛。這樣的好處是,你的核心功能跟外觀(佈景主題)完全分離,未來就算想換佈景主題,你的「專案作品」CPT 依然存在。
為了教學方便,我們先假設你選擇了比較簡單的子佈景主題方案。請打開你的子佈景主題中的 `functions.php` 檔案。
Step 2: 註冊 CPT – `register_post_type()` 函式詳解
把下面的程式碼貼到你的 `functions.php` 檔案中。別急著複製貼上,我會一行一行解釋這些設定是什麼意思。
function roamer_create_project_cpt() {
$labels = array(
'name' => _x( '專案作品', 'Post type general name', 'roamer-text-domain' ),
'singular_name' => _x( '專案作品', 'Post type singular name', 'roamer-text-domain' ),
'menu_name' => _x( '專案作品', 'Admin Menu text', 'roamer-text-domain' ),
'name_admin_bar' => _x( '專案作品', 'Add New on Toolbar', 'roamer-text-domain' ),
'add_new' => __( '新增專案', 'roamer-text-domain' ),
'add_new_item' => __( '新增專案', 'roamer-text-domain' ),
'new_item' => __( '新專案', 'roamer-text-domain' ),
'edit_item' => __( '編輯專案', 'roamer-text-domain' ),
'view_item' => __( '檢視專案', 'roamer-text-domain' ),
'all_items' => __( '所有專案', 'roamer-text-domain' ),
'search_items' => __( '搜尋專案', 'roamer-text-domain' ),
'parent_item_colon' => __( '父專案:', 'roamer-text-domain' ),
'not_found' => __( '找不到專案', 'roamer-text-domain' ),
'not_found_in_trash' => __( '垃圾桶中找不到專案', 'roamer-text-domain' ),
'featured_image' => _x( '專案封面', 'Overrides the “Featured Image” phrase for this post type.', 'roamer-text-domain' ),
'set_featured_image' => _x( '設定專案封面', 'Overrides the “Set featured image” phrase for this post type.', 'roamer-text-domain' ),
'remove_featured_image' => _x( '移除專案封面', 'Overrides the “Remove featured image” phrase for this post type.', 'roamer-text-domain' ),
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'projects' ), // 這會決定你的網址 /projects/your-project-name
'capability_type' => 'post',
'has_archive' => true, // 啟用專案作品的彙整頁面 /projects/
'hierarchical' => false,
'menu_position' => 5, // 顯示在後台選單的位置,5 是在「文章」下面
'menu_icon' => 'dashicons-portfolio', // 使用 WordPress 內建的 Dashicons 圖示
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'comments' ),
'show_in_rest' => true, // 非常重要!讓你的 CPT 支援 Gutenberg 區塊編輯器和 REST API
);
register_post_type( 'project', $args );
}
add_action( 'init', 'roamer_create_project_cpt' );
程式碼解析:
add_action('init', 'roamer_create_project_cpt');: 這行是告訴 WordPress,在它初始化完成後,去執行我們定義的 `roamer_create_project_cpt` 這個函式。CPT 必須掛載在 `init` 這個 hook 上,太早或太晚都會出錯。$labels: 這是一個陣列,用來定義 CPT 在後台各個地方顯示的文字。例如「新增文章」會變成「新增專案」,非常直觀,建議全部都設定好,使用者體驗會大大提升。$args: 這是最重要的設定陣列。'public' => true: 設為 `true` 會讓這個 CPT 在前台可見,並且會自動將 `publicly_queryable`, `show_ui`, `show_in_menu` 都設為 true,通常直接設這個就好了。'rewrite' => array('slug' => 'projects'): 設定 CPT 的網址 slug。這裡設為 `projects`,所以單一專案的網址會是 `…/projects/專案名稱/`。'has_archive' => true: 啟用彙整頁面。這樣訪客就可以透過 `…/projects/` 這個網址看到你所有的專案列表。'menu_icon' => 'dashicons-portfolio': 我最喜歡的功能之一!你可以到 Dashicons 官網挑一個喜歡的圖示,讓你的後台選單更具辨識度。'supports' => array(...): 決定這個 CPT 支援哪些 WordPress 核心功能。`title` (標題), `editor` (編輯器), `thumbnail` (特色圖片) 是最基本的。你可以根據需求增減。'show_in_rest' => true: 在這個 API 和區塊編輯器當道的時代,這個設定極度重要。設為 `true` 才能讓你的 CPT 完美支援 Gutenberg 編輯器,也才能透過 REST API 來存取資料。
Step 3: 新增專屬分類 (Custom Taxonomy)
光有 CPT 還不夠,我們還需要幫「專案作品」加上分類,例如「網頁設計」、「品牌識別」、「App 開發」。這就要用到 `register_taxonomy()` 函式。
在剛剛的 `add_action` 之前,加入以下程式碼:
// 註冊一個名為「專案分類」的分類法
function roamer_create_project_taxonomy() {
$labels = array(
'name' => _x( '專案分類', 'taxonomy general name', 'roamer-text-domain' ),
'singular_name' => _x( '專案分類', 'taxonomy singular name', 'roamer-text-domain' ),
'search_items' => __( '搜尋分類', 'roamer-text-domain' ),
'all_items' => __( '所有分類', 'roamer-text-domain' ),
'parent_item' => __( '上層分類', 'roamer-text-domain' ),
'parent_item_colon' => __( '上層分類:', 'roamer-text-domain' ),
'edit_item' => __( '編輯分類', 'roamer-text-domain' ),
'update_item' => __( '更新分類', 'roamer-text-domain' ),
'add_new_item' => __( '新增分類', 'roamer-text-domain' ),
'new_item_name' => __( '新分類名稱', 'roamer-text-domain' ),
'menu_name' => __( '專案分類', 'roamer-text-domain' ),
);
$args = array(
'hierarchical' => true, // true 的話,這個分類會像「文章分類」一樣有層級;false 則像「標籤」
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'project-category' ),
'show_in_rest' => true, // 同樣,支援 Gutenberg 和 REST API
);
// 注意第三個參數,它告訴 WordPress 這個分類法是屬於 'project' 這個 CPT 的
register_taxonomy( 'project_category', array( 'project' ), $args );
}
// 記得也要掛載到 init hook 上
add_action( 'init', 'roamer_create_project_taxonomy' );
這段程式碼的邏輯跟註冊 CPT 非常像,最關鍵的一行是 `register_taxonomy( ‘project_category’, array( ‘project’ ), $args );`。第二個參數 `array(‘project’)` 就是在告訴 WordPress:「嘿,這個新的『專案分類』是專門給『project』這個 CPT 用的喔!」
Step 4: 刷新固定網址 (Flush Rewrite Rules)
將以上程式碼都儲存後,你可能會興高采烈地去後台查看,然後點擊「檢視專案」,結果… 404 Not Found!
別慌,這是正常現象,幾乎每個 WordPress 開發者都遇過。這是因為 WordPress 還不知道你新增了 `…/projects/` 這個網址規則。你需要手動去刷新一下它的「記憶」。
方法很簡單:到 WordPress 後台的「設定」→「固定網址」,什麼都不用改,直接點擊「儲存設定」按鈕。這個動作會強制 WordPress 重建它的網址規則,你新增的 CPT 頁面就能正常顯示了。
恭喜你!到這裡,你已經成功建立了一個功能完整的 Custom Post Type,後台選單也出現了帶有帥氣圖示的「專案作品」選項,旁邊還有「專案分類」的子選單。你已經超越了 90% 的 WordPress 使用者了!
四、結語:CPT 是你邁向專業開發者的第一步
今天我們從 CPT 的概念,一路聊到動手實作,希望你對這個強大的功能不再感到陌生。學會使用 CPT,意味著你不再被 WordPress 的預設框架所限制,你可以根據客戶的任何需求,打造出邏輯清晰、易於管理的網站後台結構。這不僅能大幅提升客戶的滿意度,也是區分業餘玩家和專業開發者的重要分水嶺。
當然,CPT 的世界還很廣闊,包含如何製作專屬的頁面模板 (`archive-project.php`, `single-project.php`)、如何在主查詢中包含 CPT 的內容等等,這些都是你可以繼續深入研究的方向。但今天,你已經踏出了最關鍵的一步。
如果你覺得今天的教學對你有幫助,但又覺得實作上遇到困難,或是你的網站有更複雜的客製化需求,別忘了,浪花科技的團隊永遠在這裡。我們專精於 WordPress 深度客製化開發,從 CPT 規劃到 API 串接,都能為你提供最專業的解決方案。
延伸閱讀
- 別再被版型綁架!ACF 終極指南:用客製化欄位打造 WordPress 夢幻後台
- 改壞主題就回不去了?資深工程師手把手教你用「子佈景主題」安全客製化 WordPress!
- 別再只會分管理員和編輯!WordPress 終極權限寶典,打造滴水不漏的使用者角色管理系統
準備好讓你的 WordPress 網站脫胎換骨了嗎?立即聯繫我們,讓浪花科技的專業團隊,協助你打造一個真正符合需求的強大網站!
常見問題 (FAQ)
Q1: 什麼是自訂文章類型 (CPT)?我為什麼需要它?
A1: CPT (Custom Post Type) 是一種在 WordPress 預設的「文章」和「頁面」之外,建立全新內容類型的方法。當你需要管理的內容有特定結構(例如:作品集、產品、活動),使用 CPT 可以將這些內容與一般部落格文章分開,讓後台管理更清晰、資料更有結構,並且可以設計專屬的網址和頁面版型,大幅提升網站的專業度和可擴展性。
Q2: 我應該把 CPT 的註冊程式碼放在哪裡?`functions.php` 嗎?
A2: 直接放在佈景主題的 `functions.php` 是不推薦的作法,因為佈景主題更新時程式碼會遺失。最好的方法有兩種:1. 放在「子佈景主題」的 `functions.php` 中,確保主佈景主題更新時不受影響。 2. (更專業的做法) 建立一個專屬的功能性外掛 (Site-specific Plugin),將所有核心功能程式碼(如 CPT 註冊)放入其中,達成功能與外觀的徹底分離。
Q3: 我新增完 CPT 程式碼後,為什麼前台頁面顯示 404 找不到?
A3: 這是最常見的問題!原因是 WordPress 尚未更新它的網址重寫規則 (Rewrite Rules) 來識別你新建立的 CPT 網址結構。解決方法非常簡單:登入 WordPress 後台,前往「設定」>「固定網址」,不需要做任何修改,直接點擊頁面下方的「儲存設定」按鈕。這個動作會強制 WordPress 刷新規則,你的 CPT 頁面就能正常訪問了。






