SQL で直した記事の更新日が古いまま:post_modified を合わせてサイトマップを新しくする

広告WordPress・PHP を学べる本

Amazonのアソシエイトとして、WordPress functions.phpは適格販売により収入を得ています。

本文は直したのに、更新日が古いまま

管理しているサイトで、千件を超える記事の本文を SQL でまとめて直したあとのことです。表示はきちんと新しくなっていたのですが、サイトマップを開いてみると、記事ごとの lastmod はほとんどが前の日付のままで、最近の日付になっているのはごく一部だけでした。記事の中の構造化データの dateModified も同じく古いままです。

WordPress の記事の更新日は、wp_posts の post_modified と post_modified_gmt の 2 つの列に入っています。編集画面で保存したときや wp_update_post() を通したときは WordPress がこの列を書き換えますが、SQL で本文の列だけを直した場合は、だれも更新日を変えません。サイトマップのプラグイン(今回のサイトでは All in One SEO)も構造化データも、この列から日付を作っているので、古いまま出ていたというわけです。

更新日を変えるのは、中身を直した記事だけ

最初に決めたのは、更新日を新しくするのは、本当に中身を直した記事だけにするということです。中身を変えていない記事の日付だけを新しくすると、検索エンジンに「新しくなった」と思わせるだけの形になり、だます使い方になってしまいます。Google のサイトマップの説明でも、lastmod はページの最後の重要な更新の日時にすること、値が正確だと確認できる場合に使うことが書かれています。

そのため、条件は次の 3 つにしました。本文・タイトル・公開日は変えず、更新日の 2 つの列だけを変えます。

条件 理由
本文を直した SQL で書き換えた記事 中身が変わった記事だけを対象にする
公開中(post_status = 'publish') 下書きや非公開の記事はサイトマップに出ないので、変えない
更新日が、直した日時より前 直したあとに編集画面で保存した記事は、そちらの日付のほうが新しいので変えない。2 回流しても同じ結果になる

流す前に、戻すための SQL を作る

UPDATE を流してしまうと、前の更新日はどこにも残りません。そこで、流す前の値から「元に戻す SQL」を先に作り、ファイルにしてから進めました。戻すときは、更新日が直した日時のままの記事だけを戻すように条件を付けています。こうしておくと、UPDATE のあとに編集画面で保存し直した記事を、古い日付に戻してしまうことがありません。

戻す SQL を作る(流す前に実行して、結果をファイルに保存する)
SELECT CONCAT(
    'UPDATE wp_posts SET post_modified = ', QUOTE(post_modified),
    ', post_modified_gmt = ', QUOTE(post_modified_gmt),
    ' WHERE ID = ', ID,
    ' AND post_modified = ''2025-04-01 10:00:00'';'
)
FROM wp_posts
WHERE ID IN (12, 33, 47)
  AND post_status = 'publish'
  AND post_modified < '2025-04-01 10:00:00';
書き方 役目
QUOTE( post_modified ) 今の値を、そのまま SQL に書ける形(引用符つき)にする
AND post_modified = '…' 戻すのは、更新日が直した日時のままの記事だけ
WHERE ID IN ( … ) 本文を直した記事の ID。実際には、本文を直したときと同じ条件で選ぶ
下の 2 つの条件 このあとの UPDATE と同じ条件にして、対象の数を合わせる

この SELECT の結果の行の数は、このあとの UPDATE で変わる数と同じになるはずです。作業環境で試したとき、はじめはプログラムの中で SQL を組み立てていて、文字列の中の日時の書き方がずれ、戻す SQL が 0 行になっていたことがありました。そのときは試しの記事を別途とっておいた値で戻せましたが、それからは、戻す SQL の行の数が対象の数と同じかを、UPDATE の前に必ず確認する手順にしています。

更新日をそろえる UPDATE

中身は UPDATE 1 文だけです。日本時間で書く post_modified と、世界標準時で書く post_modified_gmt の両方を変えます。日本時間から 9 時間を引いた値が post_modified_gmt です。

更新日をそろえる(例:直した日時が 2025-04-01 10:00)
UPDATE wp_posts
SET post_modified     = '2025-04-01 10:00:00',
    post_modified_gmt = '2025-04-01 01:00:00'
WHERE ID IN (12, 33, 47)
  AND post_status = 'publish'
  AND post_modified < '2025-04-01 10:00:00';
書き方 役目
post_modified サイトの時刻(日本時間)での更新日
post_modified_gmt 世界標準時での更新日。片方だけ変えると、どちらを読むかで日付がずれる
post_status = 'publish' 下書きは変えない
post_modified < '…' 直したあとに保存し直した記事は変えない。2 回目に流しても 0 件になる

WordPress の関数にも、どちらの列を読むかを選べるものがあります。たとえば get_post_modified_time() は、2 つ目の引数で世界標準時を選ぶと post_modified_gmt を読みます。プラグインやテーマがどちらを使っているかは作りによって違うので、2 つの列はいつも合わせて変えるようにしています。

作業の順番

本番の DB に流す前に、手順を次のように決めました。

順番 すること
1 本番の DB のフルバックアップを取る
2 戻す SQL を作って、ファイルに保存する(行の数も確認する)
3 本番から複製した作業環境で UPDATE を流し、変わった数と、サイトマップの lastmod を確認する
4 本番で UPDATE を流す
5 ページキャッシュを消す(消さないと、古い日付のページやサイトマップが出続ける)
6 サイトマップの lastmod と、記事の dateModified を確認する
7 Search Console でサイトマップを送り直す

作業環境で流したところ、本文を直した公開中の記事だけ更新日が変わり、下書きは変わりませんでした。サイトマップの lastmod も、直した記事はすべて直した日時になっています。本番でも同じ手順で流してページキャッシュを消したあと、サイトマップの lastmod と記事の dateModified が直した日時になったことを確認してから、Search Console でサイトマップを送り直しました。

試しの記事で確認した結果

記事にあわせて、作業環境で公開中の記事 2 件と下書き 1 件を選び、上と同じ形の SQL を流して、元に戻るまでを確認しました。日時は試しの値にして、最後に戻しています。

確認したこと 結果
戻す SQL の行の数 2 行(公開中の 2 件の分)
UPDATE で変わった数 2 件。下書きの 1 件は変わらなかった
post_modified・post_modified_gmt 2 件とも、試しの日時と、そこから 9 時間を引いた値になった
get_post_modified_time() 2 件とも試しの日時を返した
同じ UPDATE をもう一度流す 0 件(条件の「より前」で外れる)
戻す SQL を流す 2 件が元の値に戻った
本文・タイトル・公開日 流す前と後で変わらなかった(本文とタイトルはハッシュで比べた)

WP-CLI や wp_update_post() との比べ

更新日を変えるだけなら、記事ごとに wp_update_post() を呼ぶ方法や、WP-CLI の wp post update を使う方法もあります。こちらは WordPress の処理を通るので、記事を保存したときと同じフックが動くのがよいところです。

ただし、記事を 1 件ずつ保存する形なので、件数が多いと時間がかかりますし、保存のたびにプラグインやテーマの処理(キャッシュを消す・ほかの値を作り直すなど)も 1 件ずつ動きます。更新日は保存したときの時刻になるため、本文を直した日時にそろえるには、別途指定が必要です。今回は件数が多く、変えたいのが更新日の 2 つの列だけだったので、SQL の UPDATE 1 文にしました。WP-CLI の方法は、今回は試していません。

気をつけること

  • 中身を変えていない記事の更新日だけを新しくしない。対象は、本当に直した記事だけにする
  • post_modified と post_modified_gmt は、いつも両方を合わせて変える
  • テーブルの頭(wp_)は、wp-config.php の $table_prefix に合わせる
  • SQL で直接変えたときは、ページキャッシュを消してから確認する。オブジェクトキャッシュを使っているサイトでは、そちらも消す
  • 本番で流す前に、フルバックアップと戻す SQL の両方を用意し、作業環境で数を確認しておく

まとめ

  • SQL で本文を直しても、post_modified は変わらないので、サイトマップの lastmod や dateModified は古いまま
  • 更新日を変えるのは、中身を直した公開中の記事だけにし、post_modified_gmt も合わせる
  • 条件に「更新日が直した日時より前」を追加すると、あとで保存し直した記事を巻き込まず、2 回流しても同じ結果になる
  • 戻す SQL を先に作り、行の数が対象の数と同じかを確認してから UPDATE を流す
  • 流したあとはページキャッシュを消して確認し、Search Console でサイトマップを送り直す

参考

関連機能

  1. PHP 8 で空の文字と 0 の比べ方が変わり、カテゴリーのボタンが消えた:文字と数の比べ方の変更と、テーマの直し方

  2. エックスサーバーで PHP 8.3 に上げる前に、サブドメインまで php -l で一括確認

  3. WordPress 予約投稿の失敗を解決 Scheduled Post Trigger

サイドバー

よく使うカスタマイズ

最近の記事

Profile

PAGE TOP