ローカルと本番で投稿IDがズレてた話。DB操作は全部スラッグ指定にした

WordPressの記事を、管理画面じゃなくWP-CLIやPHPスクリプトから直接いじる機会が増えてきたんですが、その中で何度も同じ事故を起こしてる罠があります。
「ローカル環境と本番環境で、同じ記事のはずなのに投稿IDが違う」ってやつです。

1回学んだつもりだったのに、また同じ手口でやらかしたので、その記録を書いておこうと思います。

最初の事故: メタディスクリプション一括更新で隣の記事を壊しかけた

公開済みの記事のうち、メタディスクリプションを設定してなかった分をまとめて埋める作業をしてたときのこと。
ローカル環境で調べた投稿IDをそのまま使って、数件ずつバッチで書き込むスクリプトを組みました。

最初のバッチを流した直後、ローカル側の全然関係ない記事に、狙ってなかったメタディスクリプションが書き込まれているのに気づきました。
一瞬「え、何が起きた」と血の気が引きました。冷や汗ものです。
原因を追ったら、対象にしていた投稿ID(56番前後)の範囲で、ローカルと本番の投稿IDが1つズレていたことが判明。
本番にはあってローカルには無い記事が1本挟まっていて、そこから後ろのIDが全部1つずつズレる形になっていました。

幸い上書きされたのはメタディスクリプションだけだったので、正しい内容に書き直せば済みました。
この時点で「IDを決め打ちで使うのは危ない」と、ちゃんと学んだつもりでした。

数日後、また同じミスをやった

内部リンクを本文に追加する作業で、また同じことをやらかしました。
今度はローカルで動作確認済みのスクリプトを、そのまま本番用に流用してしまいました。
対象は5記事。実行結果は全部found 0。まさかの全滅です。

投稿IDじゃなくスラッグを手がかりに引き直してみたら、ローカルと本番のIDは見事に全部バラバラでした。

  • ローカルID228 → 本番ID213
  • ローカルID138 → 本番ID123
  • ローカルID188 → 本番ID172
  • ローカルID128 → 本番ID113

「1つズレてる」どころか、記事によってズレ幅もバラバラ。法則性らしきものは、特に見当たりませんでした。

原因は、DBの中身がGit管理外だから

このサイトはGit+GitHubで本番に反映する仕組みを組んでいるんですが、そこで同期しているのはテーマのコード(PHP/CSS/JS)だけ。
記事やカテゴリといったDBの中身は、その仕組みの対象外になっています。

つまりローカルと本番は、投稿を作った順番やタイミングが少しでも違えば、同じ内容の記事でも別のIDが振られてしまいます。
考えてみれば当たり前の話なんですが、「同じサイトのはずだから」という思い込みで作業してると、この前提をうっかり忘れます。

対処法: IDではなく、スラッグで引く設計にする

今はDB操作のスクリプトを書くとき、そもそも投稿IDを引数に取らない設計にしています。
最初からスラッグを受け取って、PHPのget_page_by_path($slug, OBJECT, 'post')で該当の投稿オブジェクトを取得する関数だけを使う形です。

ローカルでIDベースのスクリプトを書いて動作確認するところまでは今まで通りでいいんですが、本番用に流用する前に、必ずスラッグ版へ書き直すのをルールにしました。

イメージとしては、こんな感じの書き換えです。

// 変更前: IDを直接受け取る
function update_meta($post_id, $desc) { ... }

// 変更後: スラッグから記事を特定してから処理する
function update_meta($slug, $desc) {
    $post = get_page_by_path($slug, OBJECT, 'post');
    if (!$post) { return false; }
    ...
}

ID指定だと、たとえ本番で何かしら実行できてしまったとしても、それが狙った記事とは限りません。
スラッグ指定なら、記事が見つからない時点で処理が止まります。安全弁になります。

あわせて、本番用のスクリプトを流す前にはwp post list --name=<slug>で対象記事のIDを一度目視確認する、というワンクッションも挟むようにしました。
二重の確認になりますが、事故った後だと、この一手間を惜しむ気にはもうなれません。

実際に、今この記事を書きながら同じスラッグでローカルと本番のIDを見比べてみると、こんな感じです。

ローカルとXserverの本番環境でwp post list --nameを実行し、同じスラッグの投稿IDを見比べているターミナルのスクリーンショット。ローカルは228、本番は213と表示されている

3回目でようやく事故らなかった

後日、記事末尾の「関連記事」の紐付け先を直す作業でも、同じようにローカルと本番でIDを特定する必要が出てきました。
このときは最初からスラッグ指定で組んだので、今度は何も起きずにすんなり終わりました。
2回派手にやらかしてようやく、体で覚えた感じです。地味な進歩です。

まとめ

「ローカルで動いたから本番でも同じように動くはず」というのは、コードだけの話であればその通りなんですが、DBの中身が絡む作業だと事情が変わってきます。
特にひとりで全部の工程を回してると、コードは同期されてもDBは同期されない、というギャップに気づきにくいです。

1回指摘された程度じゃ体に染み付かないタイプの罠だったので、今は「投稿IDを引数に取るスクリプトを書きそうになったら、その場でスラッグ版に直す」を機械的なルールにして運用しています。
ローカルと本番を分けてWordPressを運用している人は、一度自分の環境でもIDのズレ具合を確認してみると、思わぬところで事故を防げるかもしれません。

この記事を書いた人

Web制作歴10年近く。WordPressのテーマカスタマイズやコーディングを中心に、副業・本業ともにweb制作に携わっています。このブログでは、実際に手を動かして分かったことを書いています。

Cat's Handをフォローする

この記事が参考になったら、応援クリックをお願いします

タイトルとURLをコピーしました