前回でローカル環境が整いました。本番と同じ構成(WordPress 5.9.16 / PHP 8.2 / MySQL 8.0)を再現し、データベースのスナップショットとGitのコミットで、いつでも戻れる状態になっています。
今回は実際にアップグレードしていきます。テーマは14世代、WordPress本体は5世代。正直、どこかで大きく壊れるだろうと思っていました。
上げる順序を決める
作業に入る前に、順序を決めておく必要があります。適当にやると壊れます。
原則はこうです。
テーマ・プラグイン → WordPress本体 → PHP
理由は単純で、依存の向きがこの順番だからです。
テーマやプラグインは、特定のWordPressバージョンを前提に作られています。WordPressのコードは、特定のPHPバージョンを前提に書かれています。
古いテーマのまま新しいWordPressに上げると、テーマが対応していない機能を呼んで壊れます。古いWordPressのまま新しいPHPに上げると、削除された関数を呼んで動かなくなります。
つまり上流から順に対応させていくわけです。逆をやると、必ずどこかで詰まります。
PHPは最後
特に注意したいのがPHPです。サーバーパネルから簡単に切り替えられるので、つい先に上げたくなります。
今回のサイトはWordPress 5.9をPHP 8.2で動かしていました。5.9のリリース時点でPHP 8.2は存在していないので、公式には想定外の組み合わせです。この状態でさらにPHPを上げていたら、警告では済まずに致命的なエラーになっていた可能性が高い。
制作会社から引き継いだサイトで、クライアントが良かれと思ってPHPを上げてしまい真っ白になる、という話は珍しくありません。「サーバーパネルで上げられる」と「上げてよい」は別です。
段階的に上げる理由
もうひとつ決めたのは、一気に上げないことです。
WordPressは 5.9 → 7.1 を一発で実行することもできます。ただ、それで壊れたときに原因が特定できません。5世代分のどこかに問題があるとしか分からない。
なので、こう刻みました。
5.9.16 → 6.0.11 → 6.2.8 → 6.4.6 → 6.6.4 → 6.8.3 → 7.0 → 7.1各段階で表示を確認し、問題なければ次に進む。壊れたらその世代に原因がある、と絞り込めます。
手数は増えますが、1回あたり数分です。壊れてから原因を探す時間に比べれば、はるかに安上がりでした。
テーマを最新化する
まずテーマからです。SWELLの2.5.8.5から最新の2.19.0へ。14世代分のジャンプになります。
作業前に、現在のテーマをバックアップしておきます。Git管理から外したので、これが唯一の戻し手段です。
cp -R swell ~/Desktop/swell-2.5.8.5-backupデータベースのスナップショットも取ります。テーマは更新時にDBの設定を書き換えることがあるためです。
ddev snapshot --name=before-theme-update会員サイトから最新版をダウンロードして、差し替えます。
rm -rf swell
unzip -q ~/Downloads/swell-2.19.0.zip -d .
grep -i "Version:" swell/style.cssVersion: 2.19.0結果
サイトを開いて確認しました。トップページ、記事詳細、カテゴリ一覧、管理画面。テスト投稿も作ってみました。
まったく問題ありませんでした。
正直、拍子抜けしました。14世代も飛ばせば、どこかしら表示が崩れると思っていたからです。
理由を考えてみると、2つあります。
ひとつはSWELL側の互換性の高さです。有料テーマだけあって、バージョンアップで既存サイトを壊さないよう配慮されている。
もうひとつは、私がほとんどカスタマイズしていなかったことです。子テーマで触っていたのは、OGP画像を自動生成する部分だけ。親テーマのテンプレートを上書きしていたのは header.php など数ファイルでした。
クライアントワークのように、独自テーマでゴリゴリにカスタマイズしているサイトなら、こうはいかなかったと思います。カスタマイズが少ないほど、アップデートは楽という当たり前の事実を、身をもって確認した形です。
WordPress本体を上げる
テーマが最新のWordPressに対応した状態になったので、本体を上げていきます。
ddev wp core update --version=6.0.11 --locale=ja
ddev wp core update-dbupdate-db はデータベース構造の更新です。メジャーバージョンを上げたら必ず実行します。
以降、同じことを繰り返します。
ddev wp core update --version=6.2.8 --locale=ja
ddev wp core update-db各段階で、トップページ・記事詳細・管理画面の3点を確認しました。6.4以降はブロックエディタの変更が大きい世代なので、投稿の新規作成と保存も試しています。
結果
7.1まで、一度も壊れませんでした。
各段階でDBのバージョンが上がっていく様子は確認できました。
Success: WordPress database already at latest db version 53496. ← 6.0
Success: WordPress database already at latest db version 56657. ← 6.4
Success: WordPress database already at latest db version 57155. ← 6.6
Success: WordPress database already at latest db version 60421. ← 6.8構造の変更はきちんと入っている。それでいて表示は崩れない。WordPressの後方互換性への配慮は、かなりのものだと思います。
途中で気づいたこと
順調に進んでいた6.8の時点で、プラグインの一覧を確認しました。
ddev wp plugin listここで想定と違う状態が判明します。
| name | status | update | version | update_version | auto_update |
|------|--------|-----------|---------|----------------|-------------|
| A | active | available | 3.10.0 | 5.7.5 | off |
| B | active | available | 1.5.5 | 2.2.1 | off |
| C | active | available | 2.3.0 | 3.7.0 | off |
| D | active | available | 7.5.8 | 9.0.0 | off |
...※ プラグイン名はぼかしてA〜Dとしています。
8個すべてが4年前のバージョンのままでした。 そして auto_update はすべて off。
「自動更新が動いている」は誤読だった
第1回で、wp-content のタイムスタンプを見て、plugins ディレクトリの更新日が当日になっていることに気づきました。そのとき私は「プラグインの自動更新が動いているのだろう」と判断しました。
これが間違いでした。
実際には自動更新は無効で、1つも更新されていなかった。ではあの日付は何だったのか。
おそらく、セキュリティ系のプラグインがログや設定ファイルを書き込んだ時刻です。プラグインの中には、動作中に自分のディレクトリ配下へファイルを書き出すものがあります。ディレクトリの更新日時は「中身に変化があった時刻」なので、ログが1行増えただけでも今日の日付になります。
タイムスタンプは「何かが書き込まれた」ことしか教えてくれません。 「更新された」と解釈したのは、私の勝手な推測でした。
状態を確認するなら、素直に wp plugin list を叩けばよかった。手がかりとしてタイムスタンプは有用ですが、それだけで判断してはいけない、という教訓です。
プラグインは先に上げるべきだった
そして順序の問題もあります。
「テーマ・プラグイン → 本体 → PHP」という原則を立てておきながら、プラグインを上げないまま本体を6.8まで上げてしまっていました。自動更新が動いていると思い込んでいたためです。
幸い何も壊れませんでしたが、これは運が良かっただけです。4年前のプラグインが新しいコアで動く保証はどこにもありません。
7.0に進む前に、プラグインを1つずつ更新しました。影響の小さいものから順に、更新するたびに表示を確認する形です。
あわせて、使っていないプラグインは削除しました。8個あったものが5個になりました。プラグインが減れば、今後の保守もその分楽になります。
デフォルトテーマがGitに混入する
もうひとつ、作業中に起きた小さな事故です。
WordPressをアップグレードしていくと、その世代のデフォルトテーマ(Twenty Twenty-Three など)が自動的に追加されます。
これに気づかず git add -A でコミットしてしまい、388ファイル・12.6MB をリポジトリに取り込んでいました。プッシュまでしていたので、履歴に残っています。
前回書いた .gitignore のホワイトリスト方式は、この失敗を受けて変更したものです。
/*
!.gitignore
!VERSIONS.md
!swell_child/「除外したいものを列挙する」方式だと、予想していなかったものが増えたときに素通りします。「含めたいものだけ許可する」方式なら、何が増えても勝手に入ることはありません。
不要なテーマは削除しておきました。
ddev wp theme delete twentytwentythree twentytwentyfour twentytwentyfivePHPを上げる
すべてのアップグレードが終わってから、最後にPHPです。
ローカルならバージョンの切り替えが数十秒で済みます。8.3、8.4、8.5と順に試して、それぞれで動作を確認しました。
ddev config --php-version=8.3
ddev restart結果はいずれも問題なし。管理画面の「サイトヘルス」を見ても、PHPバージョンに関する警告は出ていませんでした。
最終的に8.5を選びました。ローカルで確認できているので、判断に根拠があります。
結果
| 項目 | 変更前 | 変更後 |
|---|---|---|
| WordPress | 5.9.16 | 7.1 |
| テーマ(SWELL) | 2.5.8.5 | 2.19.0 |
| プラグイン | 8個・すべて4年前 | 5個・すべて最新 |
| PHP | 8.2 | 8.5 |
表示崩れはゼロでした。
作業中に取ったスナップショットは9個。結局1度も戻す必要はありませんでしたが、戻せると分かっているから思い切って進められたという面はあります。保険の価値はそこにあると思います。
やってみて思ったこと
カスタマイズが少ないほどアップデートは楽です。 当たり前ですが、14世代のジャンプが無傷で通ったのは、ほぼこの一点に尽きます。逆に言えば、独自テーマでカスタマイズを重ねたサイトほど、放置期間が長引くほど身動きが取れなくなる。
段階的に上げる手間は、思ったより小さい。 1回あたり数分です。7段階で30分程度。「一気に上げて壊れたときの原因調査」に比べれば、比較にならないくらい安い保険でした。
思い込みで状態を判断しない。 タイムスタンプから「自動更新が動いている」と結論づけたのは、完全に推測でした。確認するコマンドがあるなら、それを叩くべきです。
そして、放置期間が長いサイトほど、まず現状を正確に把握することが重要だと感じました。今回で言えば、プラグインが1つも更新されていなかったという事実は、順序を決めるうえで決定的な情報でした。それを誤読したまま進んで、たまたま無事だっただけです。
このあと、ローカルで検証した内容を本番に反映しました。その作業でも別のトラブルがあったのですが、それについては別の記事に書いています。
このシリーズの第2回はこちらです。

