跳到內容

批次改分類後,排序與 Yoast 麵包屑要分開查

整理日期:2026-08-21(2026-08-24 更新)

某個作品相簿網站重新整理階層式分類後,同時出現三個狀況。

  • 分類已填入 10、20、30...,後台列表卻沒有照顯示順序排列。
  • 進入某個分類後,後台內容列表與前台分類頁沒有依內建順序排列。
  • 批次指派新分類後,部分舊內容的 Yoast 麵包屑少了最末層分類。

三件事發生在同一次分類整理,很容易以為改一個設定就能一起解決。


  • 顯示順序有沒有真的存進 term meta,以及後台列表查詢拿什麼欄位排序。
  • PHP snippet 在哪個 WordPress hook 執行,是否早於分類與內容查詢。
  • 內容的 menu_order 是否同時套用到前台與已篩選分類的後台列表。
  • WordPress 分類關聯、Yoast primary term metadata 與 Indexables 是否同步。

先把 term 排序、內容排序與 SEO metadata 分開,才不會一直重做沒有作用的索引或分類設定。


後台分類排序與前台分類排序是兩條查詢。ACF 只會保存顯示順序,不會自動改寫 WordPress 後台分類列表的 ORDER BY

第一次只在 SQL clauses 改排序,測試也只檢查 SQL 字串。正式畫面雖然看得到「顯示順序」欄,階層分類仍按名稱排列,表示測試沒有走到後台真正使用的最終 term 陣列。

另一個關鍵是 snippet 一度放在 admin_head。這時後台分類查詢已經完成,排序 filter 才註冊當然不會生效;前台也不會執行 admin_head。最後改在 plugins_loaded 註冊 filter,讓前後台查詢都能及時取得排序規則。

內容排序使用 WordPress 內建 menu_order。它屬於文章本身,同一篇內容若放進多個分類,會在所有分類共用同一個順序。

Yoast 異常則只出現在部分舊內容。異常內容即使沒有改欄位,只按一次「更新」就恢復,範圍因此縮小到單篇儲存流程與 primary term metadata。

實際重設 Indexables 並重新執行 SEO 資料最佳化後,異常仍存在。原因是重建程序會再次讀取原本錯誤的 _yoast_wpseo_primary_{taxonomy},所以索引雖然重建,錯誤的主要分類也被原樣寫回。


排序階層分類最後使用的 term 陣列

Section titled “排序階層分類最後使用的 term 陣列”

如果網站已經有 project-category-order 這類 term meta,不必再裝排序外掛。小型後台分類列表可以直接排序 get_terms 最終結果,避開 SQL JOIN,也能保留父子階層:

<?php
function site_sort_project_categories( $terms, $taxonomies, $args ) {
if (
! is_admin() ||
array( 'project-category' ) !== array_values( $taxonomies ) ||
! array_key_exists( 'page', $args ) ||
isset( $_REQUEST['orderby'] ) ||
! is_array( $terms )
) {
return $terms;
}
usort( $terms, function ( $a, $b ) {
$a_order = get_term_meta( $a->term_id, 'project-category-order', true );
$b_order = get_term_meta( $b->term_id, 'project-category-order', true );
if ( ( '' === $a_order ) !== ( '' === $b_order ) ) {
return '' === $a_order ? 1 : -1;
}
return ( (int) $a_order <=> (int) $b_order )
?: strnatcasecmp( $a->name, $b->name )
?: ( $a->term_id <=> $b->term_id );
} );
return $terms;
}
add_filter( 'get_terms', 'site_sort_project_categories', 99, 3 );

project-categoryproject-category-order 換成網站實際的 taxonomy 與 meta key。程式只接管預設列表;管理員主動點欄位排序時仍尊重那次操作,空白值會放在最後。

WPCodeBox 的 PHP snippet 應以 <?php 開始,不要保留結尾 ?>。需要同時影響前台與後台時,執行位置用 plugins_loaded,不要放在 admin_head

前台與已篩選分類的後台列表共用內容順序

Section titled “前台與已篩選分類的後台列表共用內容順序”

內容本身已有 menu_order 時,不必再建立第二個自訂欄位。只在前台分類主查詢,以及後台已篩選某個分類時改排序:

<?php
function site_project_orderby( $orderby, $query ) {
global $wpdb;
if ( ! $query->is_main_query() ) {
return $orderby;
}
if ( is_admin() ) {
if (
'project' !== $query->get( 'post_type' ) ||
! $query->get( 'project-category' ) ||
$query->get( 'orderby' )
) {
return $orderby;
}
} elseif ( ! $query->is_tax( 'project-category' ) ) {
return $orderby;
}
return "CASE WHEN {$wpdb->posts}.menu_order = 0 THEN 1 ELSE 0 END ASC,
{$wpdb->posts}.menu_order ASC,
{$wpdb->posts}.post_date DESC,
{$wpdb->posts}.ID DESC";
}
add_filter( 'posts_orderby', 'site_project_orderby', 20, 2 );

非零順序會由小到大排列,0 或未填放最後;同順位再按日期與文章 ID。後台未篩選分類時維持 WordPress 預設列表,避免不同分類的 10、20、30 混在一起。

Yoast 用一次性程序修正主要分類

Section titled “Yoast 用一次性程序修正主要分類”

先保留一篇尚未手動更新的異常頁,比較它與正常頁面的分類關聯及 _yoast_wpseo_primary_{taxonomy}。確認問題後,一次性掃描該文章類型:

  • 已指派父子分類時,選最末層分類。
  • 只有一個末層分類時,把它設為 Yoast 主要分類。
  • 有多個平行末層分類而無法判定時跳過,不任意選擇。
  • 沒有分類但殘留主要分類時,清除舊值。
  • 寫入後呼叫 Yoast 的 Primary_Term_Builder,同步主要分類資料表。

核心寫入應走 Yoast 官方類別,不要直接改資料表:

$primary_term = new WPSEO_Primary_Term( 'project-category', $post_id );
$primary_term->set_primary_term( $leaf_term_id );
YoastSEO()->classes
->get( Yoast\WP\SEO\Builders\Primary_Term_Builder::class )
->build( $post_id, 'project-category' );

實際執行結果沒有歧義或錯誤,原本缺少的末層分類也已在前台麵包屑出現。程序用 WordPress option 留下完成記錄,確認前台後即可停用並刪除。

這個修復不是永久監聽器。未來逐篇選分類並更新時通常會正常同步;若再次用批次編輯指派分類,可能重現同一問題。完成另一輪批次分類後,應改用新的執行版本再跑一次,而不是只重新啟用已完成的舊版本。

  • 不要為了觸發更新,先把全部文章批次加入再移除一個假分類。
  • 不要把 Reset Indexables 當成主要分類 metadata 的萬用修復。
  • 不要為少數舊內容直接加全站 breadcrumb filter。
  • 已經有 term meta 時,不要再裝第二套分類排序工具。
  • 不要因為後台欄位已經出現,就判定查詢排序也已生效。
  • 需要影響查詢的 PHP snippet,不要等到 admin_head 才註冊 filter。

  • taxonomy 名稱與排序 meta key。
  • snippet 的執行 hook、優先序,以及是否包含前台。
  • 階層分類中同一父層的實際順序值。
  • 文章類型、分類篩選 query var 與 menu_order
  • 一篇異常頁和一篇正常對照頁。
  • 批次修改與單篇更新分別會不會觸發問題。
  • Yoast primary term metadata 的前後值。
  • 一次性程序使用的版本 option,以及是否已經執行完成。

  • WordPress
  • 自訂分類法
  • Yoast SEO
  • WPCodeBox
  • menu_order
  • metadata