WordPress: 複数の記事で同じアイキャッチ画像 一括で変更するPHPコード

やりたいこと

僕のサイトでは、複数の記事で同じアイキャッチ画像を設定しています。
この画像を別のものに変更する場合、WordPressの仕様上は投稿画面を一記事ずつ開いて、個別に変更する必要があります。

めちゃくちゃ面倒です。

「メディアライブラリで同名のファイルに置き換えればいいのでは?」
ファイル名が同じなら、それをアイキャッチ画像として扱ってくれるはずです。
そう思って、やってみると・・・

しかし少し問題がありました。
メディアライブラリで同名のファイルがアップロードされると、ファイル名の後に-1や-2などが追加されて異なるファイルとして扱われます。
そこで既存ファイルを削除してから、アップロードしました。

そして記事を表示してみると・・・

「アイキャッチ画像が表示されない!」

仕方がないので、アイキャッチ画像を一括で変換するコードを作成しました。

アイキャッチ画像を一括変更するPHPコード

完成したのが次のコードです。
function.phpや自作プラグインに記述してください。

データベースを書き換えているので実行前にバックアップをとることをおススメします。
サイトに致命的な不具合が生じても保証できないので、コードの動作を理解したうえで、ご自分の判断で実行してください。
  • add_shortcode( 'update_eye_catch', 'my_update_eye_catch' );
  • function my_update_eye_catch( $atts ){
  • $atts = shortcode_atts(
  • array(
  • 'before' => null,
  • 'after' => null,
  • ), $atts );
  • $bf_file = $atts['before'];
  • $af_file = $atts['after'];
  • if( $bf_file === null || $af_file === null ) {
  • return '<p>エラー:このショートコードは&#91;update_eye_catch before="変更前" after="変更後"&#93;で呼び出してください</p>';
  • }
  • if( !is_numeric($bf_id = my_get_attached_id($bf_file)) ) return $bf_id;
  • if( !is_numeric($af_id = my_get_attached_id($af_file)) ) return $af_id;
  • global $wpdb;
  • $update_count = $wpdb->update( $wpdb->postmeta, array( 'meta_value' => $af_id ),
  • array( 'meta_key' => '_thumbnail_id' , 'meta_value' => $bf_id),
  • array( '%d' ), array( '%s' ,'%d') );
  • return "<p>update_eye_catch:{$update_count}個のアイキャッチを変更しました</p>";
  • }
  • function my_get_attached_id( $file_name ){
  • global $wpdb;
  • $query = "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_wp_attached_file' AND meta_value like %s";
  • $rows = $wpdb->get_results( $wpdb->prepare( $query ,$file_name ) );
  • if( count( $rows ) === 0 ){
  • return "<p>update_eye_catch:{$file_name}は、登録されていません</p>";
  • }
  • return $rows[0]->post_id;
  • }
AFFS Simple Code Viewer
Copy

使い方

  1. 変更後の画像をメディアライブラリにアップロードします。
  2. 投稿画面を表示します。
  3. 次の形式でショートコードを記述します

    [update_eye_catch before="変更前画像ファイル名" after="変更後画像ファイル名"]

  4. プレビューします。

画像ファイル名は、アップロードディレクトリの後から記述します。

wp-content/uploads/2022/04/image.png

2022/04/image.png を指定

メディアライブラリで画像編集している場合は、編集後のファイル名を指定してください。

解説:データベース仕様

アイキャッチ画像に関連するデータベース仕様について、解説します。

wp_postsテーブル

投稿画面で入力した記事データはwp_postsテーブルに保存されます。
このテーブルには、記事の他にメディアライブラリにアップロードされたファイルの情報も記憶されています。

フィールド名 意味
投稿記事 画像(添付ファイル)
ID 投稿ID
post_author 投稿者ID
post_date 投稿日 アップロード日
post_date_gmt 投稿日(GMT) アップロード日(GMT)
post_content 記事本文 画像説明
post_title 投稿タイトル 画像タイトル
post_excerpt 抜粋文 画像キャプション
post_status 投稿ステータス
'publish'(公開済)等 'inherit'(継承)固定
comment_status コメントステータス
'open'(許可) 'closed'(不許可)等
ping_status ピン・ステータス(トラックバック・ピンバック)
'open'(受け付ける) 'closed'(受け付けない)
post_password 閲覧パスワード
post_name 投稿スラッグ
to_ping ピン通知予定URL
pinged ピン通知済URL
post_modified 更新日時
post_modified_gmt 更新日時(GMT)
post_content_filtered 不明
post_parent 親記事のID
guid 記事のURL 画像のURL
menu_order メニュー内の並び順
post_type 投稿タイプ
'post' 等 'attachment' 固定
post_mime_type 空白? MIMEタイプ
'image/png' 等
comment_count コメント数

メディアライブラリで画像編集をおこなうと、ファイル名の後に -e数値 という形式で画像が生成されます。
このとき画像のguidフィールドは、新しい名前で更新されません。

wp_postmetaテーブル

wp_postmetaテーブルは、wp_postsテーブルに格納できない追加情報を保存します。
記事データと画像データ共に、アイキャッチ画像に関する追加データがあります。

フィールド名 意味
投稿記事 画像(添付ファイル)
meta_id 自動で加算される番号
post_id wp_postsテーブルのIDフィールド値
meta_key '_thumbnail_id' 固定 '_wp_attached_file' 固定
meta_value wp_postsテーブルの
IDフィールド値
(画像データ)
ファイル名
(wp-content/uploads/ 以降)

meta_keyが '_thumbnail_id' のとき、レコードは記事と画像を結びつける役割を持ちます。

'_wp_attached_file' のときは、実際のファイル名が保存されます。
メディアライブラリで画像編集をおこなうとファイル名が変更されますが、変更後の名前が保存されます。

画像削除して再アップロードするとアイキャッチが消える理由

画像削除して再アップロードするとアイキャッチが消えるのは、このデータベース仕様が原因です。

メディアライブラリで画像を「完全に削除する」で削除すると、wp_postsテーブルから画像情報が削除されます。
この時点で、wp_postmetaテーブルの画像へのIDは、存在しないレコードを指すことになります。

また、メディアライブラリで画像再アップロードすると新しいIDでレコードが作成されるので、wp_postmetaテーブルの画像へのIDは存在しないままです。

存在しない画像を見ているので、アイキャッチ画像が消えてしまうのです。

解説:PHPコード

紹介しているコードは、次のようなことをおこなっています。

  1. 変更前後のファイル名で、wp_postmetaテーブルを検索してmeta_valueを取得する。
    このとき、meta_keyが'_wp_attached_file'のものを対象とする
  2. wp_postmetaテーブルのmeta_keyが '_thumbnail_id' でmeta_valueが変更前meta_valueと一致するレコードを抽出する
  3. 抽出したレコードのmeta_value値を変更後meta_valueに置き換える。

②と③は実際には一つの関数で同時におこなっています。

データベースの書き換えをしているので少し怖いですが、やっていることは単純ですね。