【WordPress】特定条件で投稿のカスタムフィールドを一括更新する方法

【WordPress】特定条件で投稿のカスタムフィールドを一括更新する方法 WordPress

WordPressでは、カスタムフィールドを活用して投稿に独自の情報を付与することが一般的です。しかし、運用中に「特定の条件を満たす投稿だけ一括で値を変更したい」といったケースが出てくることもあります。

この記事では、カテゴリー・投稿ステータス・公開日などの条件に応じて、投稿のカスタムフィールドを一括で更新する方法を紹介します。

スポンサーリンク

functions.phpで一括更新処理を作成

以下のコードをテーマのfunctions.phpに追加することで、条件に一致する投稿のカスタムフィールドを一括更新する関数を用意します。

functions.php:一括更新する関数の定義
function update_custom_field_in_bulk() {
  // 一括更新の対象となる投稿を取得(例:特定のカテゴリIDが5の投稿)
  $args = array(
    'post_type'      => 'post',
    'posts_per_page' => -1,
    'category__in'   => array(5),
    'post_status'    => 'publish',
  );

  $posts = get_posts($args);

  foreach ($posts as $post) {
    // カスタムフィールドの値を更新
    update_post_meta($post->ID, 'your_custom_field_key', '新しい値');
  }

  return count($posts);
}

この関数は、カテゴリーIDが5の公開済み投稿に対して、your_custom_field_keyの値を新しい値に一括更新します。

安全に一度だけ実行する方法

add_action(‘init’, …)で一時実行するのは避ける
この関数をそのままadd_action('init', 'update_custom_field_in_bulk')でフックすると、サイトへのあらゆるアクセス(訪問者のページ閲覧・管理画面・Ajax・REST APIリクエストすべて)のたびに実行されてしまいます。無制限クエリ(posts_per_page => -1)とupdate_post_meta()の呼び出しが、削除し忘れている間ずっと全リクエストで走り続けることになり、サーバー負荷の原因になります。「一度実行したら削除する」という運用は、実際にアクセスのある本番サイトでは確実に1回だけの実行を保証できません。管理画面にボタンを設置し、クリックしたときだけ実行する方式が安全です。
functions.php:管理画面ボタンからの安全な実行
// 管理画面「設定」>「一般」にボタンを設置し、クリックしたときだけ実行する
function render_bulk_update_button() {
  if (!current_user_can('manage_options')) return;
  $url = wp_nonce_url(admin_url('options-general.php?run_bulk_update=1'), 'run_bulk_update');
  echo '<p><a href="' . esc_url($url) . '" class="button">カスタムフィールドを一括更新する</a></p>';
}
add_action('admin_notices', 'render_bulk_update_button');

function handle_bulk_update_request() {
  if (!isset($_GET['run_bulk_update'])) return;
  if (!current_user_can('manage_options')) return;
  check_admin_referer('run_bulk_update');

  $updated = update_custom_field_in_bulk();

  add_action('admin_notices', function () use ($updated) {
    echo '<div class="notice notice-success"><p>' . intval($updated) . '件のカスタムフィールドを更新しました。</p></div>';
  });
}
add_action('admin_init', 'handle_bulk_update_request');

「設定」>「一般」画面に表示されるボタンをクリックすると、nonceと権限チェックを経て一括更新が実行されます。実行後はコード自体を削除して構いません。

より柔軟な条件の設定例

以下のような条件で絞り込みも可能です。

日付・カスタムフィールド値による絞り込み
// 投稿日が2023年以降、特定の投稿タイプ
$args = array(
  'post_type'      => 'your_custom_post_type',
  'posts_per_page' => -1,
  'post_status'    => 'publish',
  'date_query'     => array(
    array(
      'after' => '2023-01-01',
    ),
  ),
  'meta_query'     => array(
    array(
      'key'     => 'your_custom_field_key',
      'value'   => '',
      'compare' => '=', // 既存フィールドが空文字の投稿のみ(未設定の投稿は含まない)
    ),
  ),
);

ここでの'value' => '', 'compare' => '='は、フィールドが存在していて値が空文字の投稿のみを対象にします。フィールドが一度も保存されていない(未設定の)投稿も含めて「空または未設定」を網羅したい場合は、特定のカスタムフィールドが未入力の投稿だけを抽出する方法で解説しているEXISTS/NOT EXISTSのOR結合を使ってください。

WP-CLIでの一括更新もおすすめ

大規模な投稿数がある場合は、WP-CLIを使ってサーバー側でバッチ処理を行うと高速かつ安全です。functions.phpにコードを残す必要もありません。

WP-CLIでの一括更新例
# 特定のメタキーの値を一括で更新する例(対象の投稿IDを事前に取得しておく)
wp post list --category=5 --post_status=publish --field=ID | \
  xargs -I{} wp post meta update {} your_custom_field_key "新しい値"

サーバー操作に慣れている方には特に有効な方法です。

注意点

  • 一括更新はバックアップを取った上で実施しましょう。
  • functions.phpに一時的なコードを追加する場合は、init等の全リクエストで発火するフックに直接つながず、管理画面ボタンなど明示的なトリガーを用意してください。
  • 特定の条件に基づく正確なクエリ設計が重要です。事前にテスト環境で動作確認することを推奨します。

よくある質問(FAQ)

Q条件に一致する全記事のカスタムフィールドを一括更新するには?
AWP_Queryで対象記事を全件取得し(posts_per_page=-1)、foreachでupdate_post_meta()を実行します。大量記事の場合はposts_per_page=100等でバッチ処理してタイムアウトを防ぎます。
Qwpdbを使って直接SQLでカスタムフィールドを更新するには?
A$wpdb->update($wpdb->postmeta, array(‘meta_value’ => ‘new_value’), array(‘meta_key’ => ‘my_key’, ‘meta_value’ => ‘old_value’))で一括更新できます。テーブル名は’wp_postmeta’と直接書かず$wpdb->postmetaを使うことで、テーブルプレフィックスが異なるサイトでも動作します。また$wpdbを直接操作するとWordPressのメタキャッシュが更新されないため、更新後はwp_cache_delete()での明示的なキャッシュクリアが必要になる場合があります。
Q一括更新スクリプトの実行を管理画面のボタンから起動するには?
Aadmin_post_{action}フックを使ってPOSTリクエストを処理するエンドポイントを作成し、管理画面のカスタムページにボタンを配置します。nonceによるCSRF対策を必ず実装してください。

まとめ

特定の条件に応じてカスタムフィールドを一括更新することで、データの整合性維持や運用効率化が可能になります。投稿タイプ・公開日・カテゴリ・既存のカスタムフィールド値などを条件に絞ることで、柔軟な対応ができるのがWordPressの強みです。一括更新の実行は、全リクエストで発火するフックに直接つながず、管理画面ボタンやWP-CLIなど明示的なトリガーを使うようにしましょう。

運用フローの中でこうしたバッチ処理をうまく組み込んで、より快適な管理体制を構築していきましょう。