在 WordPress 頁面列表加入自訂分類篩選下拉選單

前言

在 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;
} );