讓我們回顧一下在 Day 7 的文章中,WordPress 的資料庫架構。 WordPress 的 wp_posts
資料表並不是只有存放文章以及頁面,它是整個 WordPress 系統用來擴充功能最重要的一個資料表。
圖:WordPress 資料庫 UML 關聯圖。
而 wp_term_*
系列的資料表則為 wp_posts
資料表提供分類法 (taxonomy) 的功能支援,例如分類 (category) 、標籤 (tag) 或其它可自定義名稱的分類法。
今天的文章主要是和大家分享如何自定義文章類型、分類和標籤,為自己的 WordPress 程式開發架起無限想像力的階梯。
筆者來舉些可能可以應用的例子,當我們知道可以如何玩這個架構,學習起來才會比較有興趣。
我們可以使用自定義文章類型和分類法,達到類似 StackOverflow 網站的功能。這樣的想法不難達成,基本的設計架構,可能可以如下。
名稱 | Slug | 說明 |
---|---|---|
問題 | qna_question | 代表每一個問題。它可以有標題、內容(問題的詳情)、以及其他相關的資料,例如問題的狀態。 |
答案 | qna_answer | 代表針對特定問題的答案。可以使用 postmeta 或自訂欄位來連接答案到特定的問題,或者也可以用 parent ID 的上下層關係來建立問題和答案之間的關聯。 |
名稱 | Slug | 說明 |
---|---|---|
問題標籤 | qna_tag | 用來標記問題的主題或類別,類似於 StackOverflow 的 tags。例如,「WordPress」、「PHP」、「HTML」等。 |
問題狀態 | qna_status | 用來表示問題的狀態。例如,「未解決」、「已解決」、「重複的問題」等。 |
問題分類 | qna_category | 用於將問題分類到更廣泛的類別中,例如「前端開發」、「後端開發」、「資料庫設計」等。 |
優惠券類型的網站在以前盛行聯盟行銷的年代火紅過一陣子,很多網站會讓人建立優惠券資料,網站的使用者點擊被隱藏一半的優惠碼時會顯示完成的優惠碼,並連到目標網站,以藉此賺取佣金。這類的網站當然也可以用 WordPress 自定義文章類型和分類法來達成類似的功能架構。
名稱 | Slug | 說明 |
---|---|---|
優惠券 | coupon_post | 代表每一個優惠券。包含標題、內容、有效期限、折扣碼等。 |
商家 | store_post | 代表參與提供優惠券的商家或品牌。包含商家的名稱、描述、官方網站連結等。 |
名稱 | Slug | 說明 |
---|---|---|
優惠券種類 | coupon_type | 用來分類優惠券的類型。例如,「趴數折扣」、「買一送一」、「現金回饋」、「免運費」等。 |
優惠券分類 | coupon_category | 用於將優惠券分類到不同的產品或服務類別中。例如,「電子產品」、「服飾」、「餐廳」、「住宿」等。 |
商家種類 | store_type | 用於分類商家的類型或產業。例如,「網購」、「實體店」、「吃到飽餐廳」等。 |
地區 | coupon_region | 用來標記優惠券的適用地區或國家。例如,「台灣」、「美國」、「日本」等。 |
舉個比較耳熟能詳的例子,WooCommerce,官方的電子商務外掛。也是透過自定義文章類型和分類法來達成這個市佔率最高的電子商務解決方案。
名稱 | Slug | 說明 |
---|---|---|
商品 | product | 代表商店中的每一個產品。包含標題、描述、價格、庫存狀態等。 |
訂單 | shop_order | 代表客戶的訂單,包括訂單狀態、付款方式、送貨地址等。 |
優惠券 | shop_coupon | 表示優惠券,可以設定折扣類型、金額、適用的產品等。 |
名稱 | Slug | 說明 |
---|---|---|
商品分類 | product_cat | 用於將產品分類到不同的類別中。例如,「男裝」、「女裝」等。 |
商品標籤 | product_tag | 用來標記產品的特點或特性。例如「有機」、「手工製作」等。 |
商品運送類別 | product_shipping_class | 定義不同的運費類別。例如「標準運送」、「快速運送」等。 |
商品屬性 | pa_{屬性名稱} | 用於產品的特性,例如「顏色」、「尺寸」等。 |
以上為部分說明。詳細的官方文章說明了設計的架構,請參閱 Installed Taxonomies and Post Types 一文。
經過上一個段落的說明,展示了三種不同的可能應用場景,我們大概可以知道文章類型可以如何針對用途的不同進行擴充。
圖:WordPress 管理後台首頁
當我們進入 WordPress 的管理後台首頁時,左側導覽選單可看到文章及頁面,這可能會讓人誤以為預設的文章類型只有這兩種,其實預設文章類型有多個,只是部分因為設定參數的關係讓它們不顯示。
名稱 | 文章類型 | 說明 |
---|---|---|
文章 | post | 主要用於撰寫部落格文章。 |
頁面 | page | 靜態的內容類型,不支援時間排序。 |
附件 | attachment | 媒體文件,例如圖片、聲音或影片。每當在 WordPress 中上傳一個檔案時使用。 |
修訂版本 | revision | 表示文章或頁面的一個版本。每當儲存草稿或更新內容時保存。 |
導航選單 | nav_menu_item | 表示在導航選單中的項目。 |
範本 | wp_template | 用於 Gutenberg 區塊編輯器的範本。 |
範本組件 | wp_template_part | 用於 Gutenberg 區塊編輯器的範本組件部分。 |
在註冊文章類型時,有一個參數為 public
,設定為 true,則會顯示在選單上,設定為 false,則不顯示。
自定義文章類型使用的是 register_post_type
這個函式。
register_post_type( string $post_type, array|string $args = array() );
$post_type
(string) (必需):文章類型的名稱。只能包含小寫字母和下劃線。$args
(array|string) (可選):用於設定文章類型的參數。以下是一些常用的參數:
參數 | 類型 | 說明 |
---|---|---|
label | string | 選單中顯示的文章類型名稱。通常為複數。預設值是 $labels['name'] 。 |
labels | string[] | 此文章類型的標籤陣列。參見 get_post_type_labels()。 |
description | string | 文章類型的描述。 |
public | bool | 是否公開此文章類型。預設值為 false 。 |
hierarchical | bool | 是否為層次結構的文章類型(例如頁面)。預設值為 false 。 |
exclude_from_search | bool | 是否從前端搜尋結果中排除此文章類型的文章。 |
publicly_queryable | bool | 是否可以在前端對此文章類型進行查詢。 |
show_ui | bool | 是否在管理介面中生成並允許此文章類型的 UI。 |
show_in_menu | bool/string | 文章類型在管理選單中的顯示位置。 |
show_in_nav_menus | bool | 是否使此文章類型可用於選擇導航選單。 |
show_in_admin_bar | bool | 是否在管理欄中顯示此文章類型。 |
show_in_rest | bool | 是否在 REST API 中包含文章類型。 |
rest_base | string | 更改 REST API 路由的基本 URL。預設為 $post_type 。 |
rest_namespace | string | 更改 REST API 路由的命名空間URL。預設為 wp/v2 。 |
rest_controller_class | string | REST API 控制器類名稱。預設是 WP_REST_Posts_Controller 。 |
menu_position | int | 文章類型應出現在選單順序的位置。 |
menu_icon | string | 該選單使用的圖示的 URL。 |
capability_type | string/array | 用於建立讀取、編輯和刪除能力的字串。 |
capabilities | array | 此文章類型的權限。 |
map_meta_cap | bool | 是否使用內部預設的權限處理。 |
supports | array | 文章類型支持的核心功能。 |
register_meta_box_cb | callable | 提供設定編輯表單的額外資訊區域的回呼函式。 |
taxonomies | array | 將為文章類型註冊的分類法識別碼陣列。 |
has_archive | bool/string | 是否應該有文章類型檔案。 |
rewrite | bool/array | 觸發此文章類型的重寫處理。 |
query_var | string/bool | 為此文章類型設定 query_var 鍵。 |
can_export | bool | 是否允許導出此文章類型。 |
delete_with_user | bool | 刪除使用者時是否刪除此類型的文章。 |
template | array | 用於編輯器會話的預設初始狀態的區塊陣列。 |
template_lock | string/false | 如果設定了 $template ,則該區塊模板應鎖定。 |
圖:自定義文章類型程式碼
第 7 行:使用 register_post_type 函式進行註冊文章類型。
第 8 行:函式的第一個參數,此文章類型為 product
。
第 9 行至 19 行:函式的第二個參數,陣列格式,為更多細節設定的參數集合。
第 15 行:設定 public
為 true,則會顯示在選單及顯示其管理介面。
第 16 行:是否有彙整頁面。
第 18 行:設定選單的 ICON,這邊用了一個購物車的圖示。
動圖:自定義文章類型結果
在左側的導覽選單即出現剛剛註冊的文章類型。
自定義分類法使用的是 register_taxonomy
這個函式。
register_taxonomy( string $taxonomy, array|string $object_type, array $args = array() )
post
或 page
,或者自定義的新文章類型。以下是一些常用的參數:
欄位名稱 | 型別 | 說明 |
---|---|---|
default_term | string | array |
description | string | 該分類法的描述。 |
labels | array | 分類法的顯示文字的集合陣列。預設值分為兩種,有分層的採用「分類」,不分層的採用「標籤」 |
public | bool | 是否是為了在管理界面或前端用戶公開使用的分類法。 |
publicly_queryable | bool | 否可以公開查詢。 |
hierarchical | bool | 是否分層。 |
show_ui | bool | 是否在管理中產生 UI。 |
show_in_menu | bool | 是否在管理選單中顯示。 |
show_in_nav_menus | bool | 是否可顯示在導航選單。 |
show_in_rest | bool | 是否在REST API中包括分類法。 |
rest_base | string | 更改 REST API 路由的基本 URL。 |
rest_namespace | string | 更改 REST API 路由的命名空間 URL。 |
rest_controller_class | string | REST API 控制器類別名稱。 |
show_tagcloud | bool | 是否在標籤雲小工具控件中列出此分類法。 |
show_in_quick_edit | bool | 是否在快速編輯界面中顯示分類法。 |
show_admin_column | bool | 是否在其對應的文章類型列表顯示此分類法的欄位。 |
capabilities | array | 可使用此分類法的權限。 |
rewrite | bool | array |
query_var | string | bool |
meta_box_cb | callable | 提供顯示額外資訊區域的回呼函式。 |
update_count_callback | callable | 當計數更新時的回呼函式。 |
sort | bool | 是否應按它們提供給 wp_set_object_terms() 的順序對分類法中的字詞進行排序。 |
圖:自定義分類程式碼
第 7 行:使用 register_taxonomy 函式進行註冊文章類型。
第 8 行:函式的第一個參數,此分類為 product_category
。
第 9 行:函式的第二個參數,關聯的物件類型為 product
。
第 10 行至 18 行:函式的第三個參數,陣列格式,為更多細節設定的參數集合。
第 13 行:設定 hierarchical
為 true,則會有分層。
第 14 行:設定 show_ui
為 true,則會顯示在選單及顯示其管理介面。
第 15 行:設定 show_admin_column
為 true,在其對應的文章類型列表顯示此分類法的欄位。
動圖:自定義分類類型結果
在左側的導覽選單,滑鼠遊標移到剛剛新增的文章類型「Product」即出現剛剛註冊的「Product Categories」分類。
雖然今天的文章看起來蠻長的,不過重點在於介紹以下兩個函式的用法:
這兩個函式使用起來簡單,但其主要用途在於提供 WordPress 網站拓展功能。如果能大概瞭解使用它們可以做到什麼樣子程度的擴充,那麼在構思開發的流程時,想必會順利許多。
課後思考:
除了今天提到的三種應用情境,還有什麼點子是可以利用自定義文章類型及分類法來達成的呢?
前篇解答參考:
物件快取持久化後,可能會影響到某些需要即時性新資料的功能讀取到舊的資料。比方說,商品已售完,但因為物件持久化的資料仍處於未售完的狀況,以致於頁面顯示並沒有即時顯示給顧客造成誤解。因此在使用這樣的功能,可能需要盤點一些例外情況,特別處理。