前言
在 WordPress 後台的頁面列表中,預設並沒有提供依自訂分類法(taxonomy)篩選頁面的功能。這對於管理大量頁面且需要依分類快速查找的情境來說,十分不便。本文示範如何在頁面列表上方加入一個自訂分類的下拉選單,並讓該選單能真正影響頁面列表的查詢結果。
此範例適合對 WordPress 後台操作有基礎認識,並且希望透過程式碼自訂後台介面行為的工程師或自學者。
在頁面列表加入 taxonomy 篩選下拉選單
我們利用 restrict_manage_posts action,在頁面列表上方輸出一個下拉選單。這個下拉選單會列出指定 taxonomy(本例為 page_cat)的所有分類,讓使用者可以選擇篩選條件。
關鍵程式碼片段
add_action( 'restrict_manage_posts', function() {
global $typenow;
// 只在頁面列表顯示
if ( $typenow !== 'page' ) {
return;
}
$taxonomy = 'page_cat';
$tax_obj = get_taxonomy( $taxonomy );
if ( ! $tax_obj ) {
return;
}
$selected = isset( $_GET[$taxonomy] ) ? (int) $_GET[$taxonomy] : 0;
wp_dropdown_categories( array(
'show_option_all' => '所有 ' . $tax_obj->labels->name,
'taxonomy' => $taxonomy,
'name' => $taxonomy,
'orderby' => 'name',
'selected' => $selected,
'hierarchical' => true,
'depth' => 3,
'show_count' => false,
'hide_empty' => false,
) );
} );
這段程式碼的重點:
- 只在頁面(post_type 為
page)的列表頁顯示。 - 使用
wp_dropdown_categories()產生下拉選單,並以 taxonomy slug 作為 name,方便後續讀取。 - 透過
$_GET讀取目前選擇的分類,保持選單狀態。
利用篩選條件修改查詢結果
僅有下拉選單還不夠,我們必須讓 WordPress 查詢時根據選擇的 taxonomy 篩選頁面。這裡使用 parse_query filter,攔截後台頁面列表的查詢參數,並將 taxonomy 的 ID 轉換成 slug,塞入查詢條件。
關鍵程式碼片段
add_filter( 'parse_query', function( $query ) {
global $pagenow;
// 只在後台頁面列表
if ( ! is_admin() || $pagenow !== 'edit.php' ) {
return $query;
}
if ( ! isset( $query->query_vars['post_type'] ) || $query->query_vars['post_type'] !== 'page' ) {
return $query;
}
$taxonomy = 'page_cat';
if ( isset( $_GET[$taxonomy] ) && ! empty( $_GET[$taxonomy] ) && (int) $_GET[$taxonomy] !== 0 ) {
$term_id = (int) $_GET[$taxonomy];
$term = get_term_by( 'id', $term_id, $taxonomy );
if ( $term ) {
// 將 ID 轉為 slug,符合查詢格式
$query->query_vars[$taxonomy] = $term->slug;
}
}
return $query;
} );
這段程式碼說明:
- 僅在後台頁面列表 (
edit.php?post_type=page) 生效。 - 從
$_GET取得 taxonomy 篩選值,並轉換為 slug。 - 將 slug 設定到查詢變數中,讓 WordPress 查詢時套用此條件。
實務應用與延伸
- 可依照需求替換
$taxonomy為其他自訂分類法。 - 若頁面數量龐大,搭配分頁與排序功能使用,能大幅提升管理效率。
- 若想支援多個 taxonomy 篩選,可依此模式複製擴充。
- 注意 taxonomy slug 與分類名稱必須正確,避免查詢失效。
常見問題與注意事項
- 若 taxonomy 沒有正確註冊或名稱錯誤,篩選下拉不會顯示。
- 篩選條件若為空或 0,會顯示所有頁面。
- 轉換 ID 為 slug 是為了符合 WordPress 查詢的格式,直接用 ID 會無效。
完整程式碼
<?php
// 在「頁面列表」上方加入 taxonomy 篩選下拉
add_action( 'restrict_manage_posts', function() {
global $typenow;
// 只在「頁面」列表顯示
if ( $typenow !== 'page' ) {
return;
}
$taxonomy = 'page_cat'; // ← 換成你的 taxonomy slug
$tax_obj = get_taxonomy( $taxonomy );
if ( ! $tax_obj ) {
return;
}
$selected = isset( $_GET[$taxonomy] ) ? (int) $_GET[$taxonomy] : 0;
wp_dropdown_categories( array(
'show_option_all' => '所有 ' . $tax_obj->labels->name,
'taxonomy' => $taxonomy,
'name' => $taxonomy,
'orderby' => 'name',
'selected' => $selected,
'hierarchical' => true,
'depth' => 3,
'show_count' => false,
'hide_empty' => false,
) );
} );
// 讓剛剛那個下拉選單的值,真的用來篩選頁面
add_filter( 'parse_query', function( $query ) {
global $pagenow;
// 只在後台頁面列表 edit.php?post_type=page
if ( ! is_admin() || $pagenow !== 'edit.php' ) {
return $query;
}
if ( ! isset( $query->query_vars['post_type'] ) || $query->query_vars['post_type'] !== 'page' ) {
return $query;
}
$taxonomy = 'page_cat'; // ← 同一個 taxonomy slug
if ( isset( $_GET[$taxonomy] ) && ! empty( $_GET[$taxonomy] ) && (int) $_GET[$taxonomy] !== 0 ) {
$term_id = (int) $_GET[$taxonomy];
$term = get_term_by( 'id', $term_id, $taxonomy );
if ( $term ) {
// 把 ID 換成 slug 給查詢用
$query->query_vars[$taxonomy] = $term->slug;
}
}
return $query;
} );