2026年9月19日

2026年9月19日

WordPressの一括操作(bulk_actions)にカスタムアクションを追加する方法

WordPressの投稿一覧などにある「一括操作」のメニューには、bulk_actions-{画面ID} フィルターで独自の項目を追加し、handle_bulk_actions-{画面ID} フィルターでその処理を書くことができます。この記事では、投稿一覧に「おすすめに設定」という一括操作を追加する例を使って、項目の追加・処理・完了メッセージの表示までを、権限チェックやつまずきやすい点と合わせて説明します。

コードは子テーマの functions.php、または mu-plugin(wp-content/mu-plugins/ に置くPHPファイル)に書きます。本番に入れる前に、ステージング環境で動作を確認し、データを書き換える処理を試す前にはバックアップを取ってください。

仕組み:2つのフィルターと画面ID

一括操作の追加には、次の2つのフィルターを使います。どちらもWordPress 4.7で追加されたもので、現在も同じ名前で使えます(2026年10月現在)。

  • bulk_actions-{画面ID}:一括操作のドロップダウンに表示する項目の配列を受け取り、項目を追加・削除して返す
  • handle_bulk_actions-{画面ID}:選んだ操作が実行されたとき、リダイレクト先URL・操作名・選択された項目のID配列を受け取り、処理後のリダイレクト先URLを返す

{画面ID} は管理画面の種類ごとに決まっています。

  • 投稿一覧:edit-post
  • 固定ページ一覧:edit-page
  • カスタム投稿タイプ(例:book)の一覧:edit-book
  • ユーザー一覧:users
  • メディアライブラリ(リスト表示):upload

画面IDを間違えると、何も起きずエラーも出ないため、最初につまずきやすい点です。分からないときは、対象の画面で get_current_screen()->id を確認します。

手順1:一括操作の項目を追加する

投稿一覧のドロップダウンに「おすすめに設定」を追加します。配列のキーが操作名(プログラム側で使う識別子)、値が画面に表示される名前です。

add_filter( 'bulk_actions-edit-post', function ( $actions ) {
	$actions['my_mark_featured'] = __( 'おすすめに設定', 'my-site' );
	return $actions;
} );

操作名には、他のプラグインやWordPress本体と重ならないよう接頭辞(ここでは my_)を付けます。本体の操作名である trash や edit と同じ名前にすると、本体の処理が先に動いてしまいます。

手順2:選択された項目を処理する

次に、操作が実行されたときの処理を書きます。ここでは、選択された投稿にカスタムフィールド _my_featured を設定します。

add_filter( 'handle_bulk_actions-edit-post', function ( $redirect_url, $action, $post_ids ) {
	if ( 'my_mark_featured' !== $action ) {
		return $redirect_url;
	}

	$done = 0;
	foreach ( $post_ids as $post_id ) {
		$post_id = (int) $post_id;
		// 投稿ごとに編集権限を確認する
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			continue;
		}
		update_post_meta( $post_id, '_my_featured', 1 );
		$done++;
	}

	$redirect_url = remove_query_arg( 'my_featured_done', $redirect_url );
	return add_query_arg( 'my_featured_done', $done, $redirect_url );
}, 10, 3 );

ポイントは3つあります。

1つ目は、自分の操作名以外のときは受け取ったURLをそのまま返すことです。このフィルターには他のプラグインの一括操作も流れてくるため、条件分岐を忘れると他の機能を壊します。

2つ目は、権限の確認です。投稿一覧などの標準の画面では、WordPress本体が一括操作用の nonce を検証してからこのフィルターを呼び出します。一方、「その投稿を編集してよいか」は投稿ごとに異なるため、current_user_can( 'edit_post', $post_id ) で1件ずつ確認します。他人の投稿を編集できない「投稿者」権限のユーザーでも一括操作のメニュー自体は見えるので、この確認を省くと権限を越えた書き換えが起きます。

3つ目は、戻り値です。このフィルターはリダイレクト先のURLを返す必要があり、処理件数などの結果はURLのクエリ引数に載せて次の画面に渡します。何も返さないと一覧画面に正しく戻れません。

手順3:完了メッセージを表示する

リダイレクト後の画面で、クエリ引数を読み取ってメッセージを表示します。

add_action( 'admin_notices', function () {
	if ( ! isset( $_GET['my_featured_done'] ) ) {
		return;
	}
	$screen = get_current_screen();
	if ( ! $screen || 'edit-post' !== $screen->id ) {
		return;
	}
	$count = absint( $_GET['my_featured_done'] );
	printf(
		'<div class="notice notice-success is-dismissible"><p>%s</p></div>',
		esc_html( sprintf( '%d件の投稿をおすすめに設定しました。', $count ) )
	);
} );

// メッセージ表示後、URLからクエリ引数を取り除く
add_filter( 'removable_query_args', function ( $args ) {
	$args[] = 'my_featured_done';
	return $args;
} );

URLの値は利用者が書き換えられるため、absint() で整数にし、出力時は esc_html() でエスケープします。removable_query_args フィルターに登録しておくと、表示後にブラウザのアドレス欄から引数が消え、再読み込みでメッセージが繰り返し出ることを防げます。

手順4:カスタム投稿タイプやユーザー一覧に広げる

複数の投稿タイプに同じ操作を追加したい場合は、画面IDを変えて同じ関数を登録します。

foreach ( array( 'post', 'page', 'book' ) as $post_type ) {
	add_filter( "bulk_actions-edit-{$post_type}", 'my_add_featured_action' );
	add_filter( "handle_bulk_actions-edit-{$post_type}", 'my_handle_featured_action', 10, 3 );
}

この場合は手順1・2の無名関数を my_add_featured_action などの名前付き関数に書き換え、完了メッセージの画面IDの判定も対象の画面に合わせて変更します。

ユーザー一覧(画面ID users)では、3つ目の引数がユーザーIDの配列になります。権限の確認は current_user_can( 'edit_user', $user_id ) を使います。メディアライブラリはリスト表示のときだけ一括操作のメニューが使え、グリッド表示では動作が異なる点に注意してください。

つまずきやすい点と確認方法

  • 項目が出ない:画面IDの綴り(edit-post のハイフン)と、フィルター名の綴りを確認する。コードが読み込まれているかは、子テーマが有効か、mu-plugin のファイルが直下に置かれているかで確認する
  • 処理が動かない:handle_bulk_actions- の画面IDと操作名が手順1と一致しているか、add_filter の第4引数(受け取る引数の数)が 3 になっているかを確認する
  • 一部の投稿だけ処理されない:権限の確認で除外されている可能性がある。処理件数と除外件数を分けてメッセージに出すと原因を追いやすい
  • 大量の投稿で止まる:一括操作の対象は、一覧に表示されている1ページ分だけです。表示件数を増やして数百件を一度に処理すると、時間切れになることがあります。重い処理や大量のデータには、WP-CLI のコマンドや、バックグラウンドで順に処理する仕組み(「Action Scheduler」など)を使う方が安全です

動作確認では、管理者だけでなく、編集者や投稿者など権限の異なるユーザーでもログインして試してください。

まとめ

  • 項目の追加は bulk_actions-{画面ID}、処理は handle_bulk_actions-{画面ID} フィルターで行う
  • 処理側では自分の操作名だけを扱い、他の操作のときは受け取ったURLをそのまま返す
  • nonce の検証は標準の一覧画面では本体が行うが、項目ごとの権限は current_user_can() で自分で確認する
  • 結果はクエリ引数で渡し、absint() と esc_html() を通して表示する。removable_query_args で後始末をする
  • 大量処理は一括操作ではなく WP-CLI やバックグラウンド処理に任せる

お気軽にご相談ください

お見積りへ お問い合わせへ
▲