はじめに
以下を実現します。
外観→メニューのメニュー位置で設定したメニューのカテゴリーに投稿数を表示します。
この記事では、この方法について説明します。
完成イメージ

実装手順
以下のコードをfunctions.phpに追加します。
add_filter('wp_nav_menu_objects', function ($items, $args) {
// 対象のメニュー位置
$target_locations = [
'navi-header', // ヘッダーメニュー
'navi-mobile', // ヘッダーモバイルメニュー
'navi-header-mobile', // ヘッダーモバイルボタン
'navi-footer', // フッターメニュー
'navi-footer-mobile', // フッターモバイルボタン
'navi-mobile-slide-in', // モバイルスライドインメニュー
];
// 対象外の位置の場合
if (empty($args->theme_location) || !in_array($args->theme_location, $target_locations, true)) {
return $items;
}
foreach ($items as $item) {
if ($item->object === 'category') {
$category = get_category($item->object_id);
if (isset($category->count)) {
$item->title .= sprintf(' (%d)', $category->count);
}
}
}
return $items;
}, 10, 2);
補足
メニューも投稿の一部として扱われ、データベースのwp_postmetaの拡張で情報が管理されます。
表1にメニューの情報を示します。
| キー | 内容 |
|---|---|
| _menu_item_type |
|
| _menu_item_menu_item_parent | 1=親メニュー |
| _menu_item_object_id | オブジェクトID |
| _menu_item_object |
|
| _menu_item_target | 1=_blank |
| _menu_item_classes | CSS class |
| _menu_item_xfn | |
| _menu_item_url | カスタムリンクのURL |
array(8) {
["_menu_item_type"]=>array(1) {
[0]=>string(9) "post_type"
}
["_menu_item_menu_item_parent"]=>array(1) {
[0]=>string(1) "0"
}
["_menu_item_object_id"]=>array(1) {
[0]=>string(4) "7949"
}
["_menu_item_object"]=>array(1) {
[0]=>string(4) "page"
}
["_menu_item_target"]=>array(1) {
[0]=>string(6) "_blank"
}
["_menu_item_classes"]=>array(1) {
[0]=>string(22) "a:1:{i:0;s:5:"class";}"
}
["_menu_item_xfn"]=>array(1) {
[0]=> string(0) ""
}
["_menu_item_url"]=>array(1) {
[0]=>string(0) ""
}
}
参考:ボックスメニューのカテゴリーに投稿数を表示
以下のメニューにも投稿数を表示します。
- ボックスメニュー
- おすすめカード
- ナビカード
完成イメージ

実装手順
以下のコードをfunctions.phpに追加します。
add_filter('wp_get_nav_menu_items', function ($items, $menu, $args) {
// 対象とする関数名
$target_functions = [
'get_box_menu_tag', // ボックスメニュー
'get_navi_card_list_tag', // おすすめカード、ナビカード
];
// 呼び出し元関数名の配列
$caller_functions = array_column(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10), 'function');
// 対象関数が呼び出し元に含まれない場合
if (empty(array_intersect($target_functions, $caller_functions))) {
return $items;
}
foreach ($items as $item) {
// メニューアイテムがカテゴリーの場合
if ($item->object === 'category') {
$category = get_category($item->object_id);
if (isset($category->count)) {
$item->title .= sprintf(' (%d)', $category->count);
}
}
}
return $items;
}, 10, 3);
補足
WordPressで特定コンテキスト(ボックスメニューやナビカード等)だけに処理を適用したい場合、大きく分けてバックトレース方式とショートコードフック方式の2つが存在します。
それぞれ明確なメリット・デメリットや対応範囲の違いがあります(表2参照)。
| 項目 | バックトレース方式 (debug_backtrace) | ショートコードフック方式 (pre/do_shortcode_tag) |
|---|---|---|
| コード構成 | フック1つでコンパクトに完結 | 開始/終了フックの2箇所が必要 |
| ウィジェット対応 | 完全対応 | 非対応 |
| 保守性 | テーマ内部の関数名変更で動作停止リスク | 公開ショートコード名指定のため変更リスク低 |
| 処理コスト | スタックトレースを展開するためわずかに重い | 必要な瞬間だけフック登録するため超軽量 |
ショートコードフック方式のコードを以下に示します。
// 対象ショートコードの実行直前に実行
add_filter('pre_do_shortcode_tag', function ($output, $tag) {
if (in_array($tag, get_category_count_target_shortcodes(), true)) {
// フィルターを追加
add_filter('wp_get_nav_menu_items', 'add_category_count_to_menu_items', 10);
}
return $output;
}, 10, 2);
// 対象ショートコードの実行完了直後に実行
add_filter('do_shortcode_tag', function ($output, $tag) {
if (in_array($tag, get_category_count_target_shortcodes(), true)) {
// 追加したフィルターを解除
remove_filter('wp_get_nav_menu_items', 'add_category_count_to_menu_items', 10);
}
return $output;
}, 10, 2);
/**
* 件数追加の対象とするショートコード名一覧
*
* @return array
*/
function get_category_count_target_shortcodes() {
return [
'box_menu', // ボックスメニュー
'navi_list', // ナビカード、おすすめカード
];
}
/**
* メニューアイテムがカテゴリーの場合に記事数をタイトルへ追加
*
* @param array $items メニューアイテムの配列
* @return array 記事数が追加されたメニューアイテムの配列
*/
function add_category_count_to_menu_items($items) {
foreach ($items as $item) {
if ($item->object === 'category') {
$category = get_category($item->object_id);
if (isset($category->count)) {
$item->title .= sprintf(' (%d)', $category->count);
}
}
}
return $items;
}


