WordPress を長く運用していると、「公開日」よりも「更新日」が古い、つまり post_modified < post_date という不自然な状態になる記事が紛れ込むことがあります。
この状態は、テーマ・プラグイン・インポート処理などが原因で起こることがあり、SEO や表示上の整合性に影響を与えることもあります。
以下の記事では、WordPress の functions.php に一時的に追加するだけで、そうした記事を自動で検出し、更新日を公開日に揃えるスクリプトを紹介します。
実際のコードとともに、「なぜこういうズレが起こるのか」「使い方」「注意点」なども詳しく解説します。
えりコードの使用は自己責任でお願いします。
一度テスト環境で実行やバックアップを取ってからの実行がおすすめです。
リード文
Webサイトを運営していると、過去の記事を手動で編集したり、インポートツールを使ったりした際に「更新日」が公開日より前になってしまうケースがあります。
見た目には気づきにくいけれど、SEO やユーザーの信頼感に影響する可能性もあります。
この記事では、WordPress の functions.php に記載するだけで、そうしたズレを自動検出し修正するスニペットを紹介します。
導入方法から注意点まで丁寧に解説しますので、安心して取り入れていただけます。
なぜ更新日 < 公開日 というズレが発生するのか?
まず、WordPress における日付フィールドの構造を簡単に振り返っておきます:
| フィールド | 意味 |
|---|---|
post_date / post_date_gmt | 投稿が公開された日時 |
post_modified / post_modified_gmt | 投稿が最後に「更新」された日時 |
通常、記事を更新すると post_modified 側が現在時刻に書き換えられます。
しかし、何らかの要因でその動作が正しく行われない、あるいはインポート/移行処理でタイミングのズレがあると、post_modified < post_date という奇妙な状態になることがあります。
例えば:
- インポートやマイグレーションプラグインが
post_dateは反映するがpost_modifiedを更新しないことがある - 既存データを直接 SQL で操作した結果、更新日は変更されないままになる
- WordPress コアの挙動として、
wp_insert_post()においてpost_modifiedを意図した通りに反映できないバグ報告もある (core.trac.wordpress.org) - スケジュール投稿(future → publish)に変換されるとき、公開日に合わせて更新日を追随させないケースも指摘されている (contentpowered.com)
このようなズレを放置すると、テーマやプラグインが「更新日順でソート」「最終更新日を表示」などを行う際に見栄えが崩れたり、読者に違和感を与えたり、SEO における信頼性に微妙な影響を及ぼすことがあります。
スニペットの全体像(コード)
以下が、今回紹介するスニペットの全体コードです。WordPress のテーマの functions.php やカスタムプラグイン(管理用に限定的なもの)に追加して使います。
/**
* すでに公開済みの記事のうち、
* 「更新日 < 公開日」になっているものを修正するスクリプト
*/
function fix_past_posts_modified_dates() {
// 管理者のみ実行(不必要なアクセス防止)
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
global $wpdb;
// 公開済みの投稿・固定ページのうち、更新日が公開日より古いものを取得
$posts = $wpdb->get_results("
SELECT ID, post_date, post_date_gmt
FROM {$wpdb->posts}
WHERE post_status = 'publish'
AND (post_type = 'post' OR post_type = 'page')
AND post_modified < post_date
");
if ( ! empty( $posts ) ) {
foreach ( $posts as $post ) {
$wpdb->update(
$wpdb->posts,
array(
'post_modified' => $post->post_date,
'post_modified_gmt' => $post->post_date_gmt,
),
array( 'ID' => $post->ID )
);
clean_post_cache( $post->ID );
}
echo '<div class="notice notice-success"><p>更新日を修正しました(' . count( $posts ) . '件)。</p></div>';
} else {
echo '<div class="notice notice-info"><p>修正対象の投稿はありません。</p></div>';
}
}
add_action( 'admin_notices', 'fix_past_posts_modified_dates' );
このコードの流れを順を追って見てみましょう。
スニペット解説 — 各部分の意味と注意点
管理者権限チェック
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
この一文により、管理者ユーザーのみがこの処理を実行できるよう制限しています。
一般ユーザーがサイトを閲覧したときにこのスクリプトが働くと誤動作のリスクがありますから、このような制御は非常に重要です。
SQL で対象記事を取得
$posts = $wpdb->get_results("
SELECT ID, post_date, post_date_gmt
FROM {$wpdb->posts}
WHERE post_status = 'publish'
AND (post_type = 'post' OR post_type = 'page')
AND post_modified < post_date
");
post_status = 'publish':公開済みの記事・固定ページに限定post_type = 'post' OR post_type = 'page':投稿と固定ページを対象にpost_modified < post_date:更新日が公開日より過去のレコードを抽出
取得するカラムは ID、post_date、post_date_gmt のみです。ここでは、更新すべき基準となる「公開日の値」を用いて、更新日の修正に使います。
更新処理とキャッシュクリア
$wpdb->update(
$wpdb->posts,
array(
'post_modified' => $post->post_date,
'post_modified_gmt' => $post->post_date_gmt,
),
array( 'ID' => $post->ID )
);
clean_post_cache( $post->ID );
wpdb->update():wp_postsテーブルを直接更新post_modified/post_modified_gmtにpost_date/post_date_gmtの値を上書きclean_post_cache():更新後にキャッシュをクリアして、表示側に反映されやすく
データベースを直接操作するため、確実に動く反面、注意も必要です。
管理画面上への通知出力
echo '<div class="notice notice-success"><p>更新日を修正しました(' . count( $posts ) . '件)。</p></div>';
もしくは対象がなければインフォメーションタイプで通知を出します。これにより、どれだけの記事が修正されたかを目視で確認できます。
フックによる実行タイミング
add_action( 'admin_notices', 'fix_past_posts_modified_dates' );
このフックにより、管理画面の通知領域を描画するタイミングでスクリプトが走ります。つまり、管理画面の表示時に一度だけチェック・修正するように設計されています。
スニペットの使い方・導入手順
以下の手順で導入できます:
- バックアップを取る
— データベースとファイルは必ずバックアップしておきましょう。直接 SQL 更新を行う処理なので、万一の不具合に備える必要があります。 - 子テーマ or 管理専用プラグインへ記述
— 親テーマのfunctions.phpに書くとテーマ更新で消える可能性があります。安全性を考えると子テーマか、運用後に取り除ける “管理専用のカスタムプラグイン” に記述するのが望ましいです。 - 管理画面を表示
— WordPress 管理画面を開くと、通知領域に「更新日を修正しました(X 件)」などのメッセージが出て処理が実行されます。 - 処理が完了したら削除
— 一度走らせて修正したら、その後は必要ないためコードを削除してください。常時残したままだと毎回 SQL を走らせることになり、無駄な負荷になる可能性があります。 - 修正後のチェック
— 投稿一覧画面、あるいは REST API・テーマの “最終更新日” 表示箇所を確認し、ズレが解消されているかを確認します。
注意点・リスクと対応策
このような直接更新スクリプトを使う際は、以下の点に注意してください。
キャッシュ・オブジェクトキャッシュの影響
- オブジェクトキャッシュ(Redis, Memcached 等)を使っている場合、キャッシュされた古いデータが残る可能性があります。
clean_post_cache()を呼んでいますが、場合によってはキャッシュプラグインの影響で反映されにくいこともあります。 - フロントエンドキャッシュ(CDN やページキャッシュ)も併せてクリアしたほうが安全です。
他プラグイン・テーマとの競合リスク
- 一部プラグインやテーマは公開・更新フックでカスタムな動作をすることがあります。そういった処理と干渉する可能性があります。
- スクリプトが意図せず動く範囲をきちんと限定(管理画面限定、権限チェック)しておくのはこのためです。
パフォーマンスに注意
- 投稿数が非常に多いサイトでは、この SQL 検索自体が重くなる可能性があります。数十万件以上の記事があるサイトでは、条件を絞るか複数回に分けて実行するなど工夫が必要です。
- 一度で全件処理するのではなく、例えば日付別範囲を限定して処理するよう改良しても良いでしょう。
繰り返し実行を避ける
このスクリプトを残し続けると、毎回管理画面を開くたびに SQL 更新チェックが走ります。不要になったら必ず削除または無効化しましょう。
権限チェックを絶対に残す
current_user_can( 'manage_options' ) チェックは必須です。一般ユーザーにまで実行されてしまうと、不測の更新を招く恐れがあります。
カスタマイズ例:スケジュール投稿の即時対応
先述したように、スケジュール投稿(future → publish)時には、公開日時に合わせて更新日を同期したいケースがあります。この用途には、以下のようなフックを使った応用があります: (contentpowered.com)
function update_modified_date_to_post_date( $post_id, $post ) {
if ( empty( $post ) || $post->post_type !== 'post' ) {
return;
}
wp_update_post( [
'ID' => $post_id,
'post_modified' => $post->post_date,
'post_modified_gmt' => $post->post_date_gmt,
] );
}
add_action( 'future_to_publish', 'update_modified_date_to_post_date', 10, 2 );
このコードを併用すれば、スケジュール投稿が公開されるタイミングで「更新日 = 公開日」に揃えるようにできます。ただし、こちらも過度に残すと更新ごとの処理負荷になりますので、用途に応じて使い分けるとよいでしょう。
導入後チェックリスト
- 対象となった投稿が適切に “更新日 = 公開日” に修正されている
- 管理画面やテーマで表示される最終更新日が期待通りになっている
- キャッシュ(オブジェクトキャッシュ・CDN・ページキャッシュ等)をクリアして影響を確認
- コードを削除またはコメントアウトして再度管理画面を開き、通知が出ないことを確認
- 定期的に(たとえば月 1 回など)サイト上に同様のズレがないかチェックする仕組みを考える
このスニペットを使うことで、過去の記事の 不整合な更新日をまとめて修正 でき、見た目の整合性や信頼性を取り戻すことができます。
もしご希望であれば、投稿数が多いサイト向けにバッチ処理化する方法や、より安全な実装バージョンも提示できますので、必要でしたらお知らせください。




コメント