
WordPressカスタムHTMLブロックが編集画面で消える原因と直し方
WordPress のブロックエディターでカスタム HTML ブロックを保存後に編集画面を開き直すと、ブロックの中身がまるごと消えて空欄に見える現象は、Gutenberg の React 側パーサーが HTML 構造を正しく解析できずに描画を放棄しているのが主な原因だ。script タグや閉じタグのない要素、複雑なインラインスタイルなどが引き金になる。
なぜカスタムHTMLブロックが編集画面で空になるのか

フロントエンドでは正しく表示されるのに、管理画面のブロックエディターだけで中身が空になるのは、データそのものはデータベースに保存されている証拠だ。コードエディターモードに切り替えれば、貼り付けた HTML が消えずに残っているのが確認できる。この現象が起こるのは、ブロックエディターがビジュアルモードでブロック内容を再表示するときに、DOM パーサーが特定の HTML を「壊れた構造」と判断してレンダリングを飛ばしてしまうからだ。
具体的には、Gutenberg が内部的に使用している React の DOM レンダリング機構が、管理画面の安全な枠組みの中で処理できないタグや構文に遭遇すると、そのブロック全体を安全のためにスキップする。結果として視覚的には空のブロックに見えるが、データベースの post_content には元のコードがそのまま格納されている。
カスタムHTMLブロックの中身が消える原因を特定する手順

まず、どの部分が問題を引き起こしているのかを切り分ける。以下の手順で原因箇所を絞り込む。
ブロックエディターのコードエディターモードで現状を確認する
編集画面右上の「︙」メニューから「コードエディター」を選択すると、ビジュアル表示ではなく生の HTML 構造が表示される。カスタムHTMLブロック内のコードがここで確認できれば、データは失われていない。このとき、Markdown 記法でブロック境界を示す <!-- wp:html --> と <!-- /wp:html --> のコメント行の内側にコードが残っているかを確かめる。
HTMLを最小単位に分解して原因のタグを特定する
ブロックに貼り付けた HTML を、1つのタグ単位で分割してカスタムHTMLブロックに1つずつ入れ直す。たとえば script タグ、style タグ、空要素(<div></div> など)、インラインイベントハンドラ(onclick など)をそれぞれ別のブロックに分けて保存し、再読み込み時に消えるかどうかをテストする。問題を起こすタグが特定できれば、その部分だけ別の実装方法に切り替えられる。
プラグイン競合の可能性を調べる
特定のプラグインがブロックエディターの動作に干渉して、カスタムHTMLブロックの描画を阻害しているケースもある。特にエディター拡張系のプラグインや、セキュリティ目的でスクリプトをフィルタリングするプラグインが入っている場合は、すべてのプラグインを一度無効化して標準テーマに切り替え、問題が再現するか確認する。プラグインが原因であれば、1つずつ再有効化して犯人を特定する。
カスタムHTMLブロックを正常に表示させる具体的な修正手順

原因が特定できたら、次は実際にブロックを正常に表示させる。script タグや複雑な HTML 構造が原因だった場合、以下のアプローチで回避できる。
script タグや iframe はカスタムHTMLブロックではなく適切な場所に配置する
Gutenberg のカスタムHTMLブロックは、セキュリティ上の理由から script タグの実行を制限している。また、ビジュアルエディターでの再レンダリング時に script タグを含むブロックを空として扱う挙動が確認されている。JavaScript を埋め込みたい場合は、カスタムHTMLブロックではなく、functions.php に wp_enqueue_script で登録するか、専用のコード埋め込みプラグインを使う。iframe も同様に、エディターのプレビューで空白になることがあるため、フロントエンドのみで描画される仕組みを検討する。
閉じタグのない空要素を見直す
カスタムHTMLブロックに <div></div> のような中身のない空タグや、閉じタグを省略した要素が含まれていると、Gutenberg のブロックパーサーが構造を正しく解釈できずにブロック全体をスキップすることがある。空の div や span は削除するか、 を入れて実体を持たせる。とくに WordPress の自動整形機能(wpautop)が余分な p タグや br タグを挿入することで、意図しない空要素が生まれることもある。
複雑なHTML構造はカスタムフィールドやショートコードに置き換える
テーブルやフォーム、装飾を多用したマークアップは、カスタムHTMLブロック1つにまとめるよりも、ACF(Advanced Custom Fields)のテキストエリアフィールドや、ショートコード化して出力する方が安定する。とくにクライアントが自分で編集する前提のサイトでは、カスタムHTMLブロックを直接触らせると今回のようなトラブルが再発しやすい。テーマ側でテンプレートパーツとして管理し、投稿画面では入力欄だけを提供する設計が安全だ。
今後同様のトラブルを防ぐための運用ポイント

カスタムHTMLブロックに貼り付ける前にコード検証を行う
外部の HTML スニペットをそのまま貼り付ける前に、W3C のバリデーターや VSCode の構文チェック機能でタグの閉じ忘れや文法エラーがないかを確認する。コピー元の Web ページから取得したコードには、不要な属性や非推奨のタグが混じっていることが多い。貼り付け前に一度テキストエディターにペーストし、明らかな問題を取り除いてからブロックに入力する習慣をつける。
WordPress と Gutenberg を最新バージョンに保つ
Gutenberg プラグインを単体でインストールしている場合は、定期的に更新することでブロックパーサーの改善や既知の不具合修正が適用される。コア組み込みのブロックエディターであっても、WordPress 本体のアップデートによってパースエンジンの挙動が改良されることがある。編集画面でカスタムHTMLブロックが空になる現象の一部は、過去のバージョンで修正されたバグに起因している可能性もあるため、まずは最新の状態であることを確認する。
どうしても必要な場合はコードエディターモードを常用する
ビジュアルエディターで空になってしまう HTML をどうしてもページに残したいときは、編集時にコードエディターモードに切り替えて作業する方法が最終的な回避策になる。データベースにコードが正しく保存されているなら、コードエディター表示では常に中身が確認できる。手間は増えるが、複雑なマークアップや埋め込みコードを扱うページでは、あらかじめこの運用を前提にしておくとトラブルが起きても編集が止まらない。
よくある質問
カスタムHTMLブロックの中身は完全に消えたのか
ビジュアルエディターでは空に見えても、コードエディターモードに切り替えると HTML が残っていることがほとんどだ。データベースの post_content にも保存されているため、失われたわけではない。
プラグインをすべて無効化しても直らない場合はどうすればいいか
テーマの functions.php や使用中の子テーマがエディターの動作に干渉している可能性がある。標準テーマ(Twenty Twenty-Five など)に一時的に切り替えて再現するか確認し、テーマ側のフィルターやアクションを調査する。
script タグをカスタムHTMLブロックで使う正しい方法はあるか
原則としてカスタムHTMLブロック内の script タグは推奨されない。管理画面でのレンダリング問題に加え、セキュリティプラグインやサーバー側のフィルターで除去されるリスクもある。どうしても必要な場合はショートコード化するか、wp_enqueue_script でテーマに登録するのが安全だ。
ビジュアルエディターで空白になる特定の HTML タグの一覧はあるか
公式の一覧は存在しないが、script タグ、style タグ、iframe、object、embed、空の div や span、コメントアウト行、複雑に入れ子になったインラインスタイル付き要素などが報告されている。問題が起きたら該当タグを一つずつ検証するのが確実だ。
ビジュアルエディターで空になる現象は Gutenberg のバグなのか
仕様とバグの両面がある。script タグの実行制限はセキュリティ上の意図的な制限であり、空要素のパース失敗はブロックエディターの改善が期待される領域だ。WordPress コアのバージョンアップによって挙動が変わることもあるため、最新バージョンへの更新が有効な場合が多い。
この記事のポイント
- カスタムHTMLブロックが空に見えてもデータはデータベースに残っている
- script タグや空要素、閉じタグ省略がパース失敗の主原因
- コードエディターモードで中身を確認し原因タグを特定する
- 複雑な HTML はカスタムフィールドやショートコードで管理する
- WordPress と Gutenberg の最新化で改善するケースがある

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WooCommerce Taxが配送先住所を無視する原因と修正手順
WooCommerceの自動税計算(WooCommerce Tax)が配送先住所を無視して店舗住所の税率を適用し続ける場合、設定のキャッシュか配送先住所の認識不良が原因だ。税計算の基準を再確認し、プラグインのトランジェントデータを手動で削除すれば、多くのケースで正しい税率に戻る。
配送先住所ではなく店舗住所の税率が使われる原因

WooCommerce Tax(旧称 WooCommerce Shipping & Tax)は、有効化すると TaxJar の自動税率データベースを参照して税額を算出する。管理画面の「WooCommerce > 設定 > 税」で「顧客の配送先住所に基づいて計算する」を選択しているにもかかわらず店舗住所の税率が使われるのは、次のいずれかが起きていると考えられる。
- 税計算の基準設定が実際には店舗住所のまま保存されていない、または別のフィルターで上書きされている
- プラグインが内部に保持するトランジェントキャッシュが古い設定を返し、配送先住所を無視している
- チェックアウト時に配送先住所が正しくシステムに渡っていない(テーマや他のプラグインによる競合)
- WooCommerce Tax が店舗の税ネクサス(課税拠点)を元にした「オリジンベース課税」のルールを配送先住所より優先してしまっている
特に最後の点は、米国のように州ごとにオリジンベース/デスティネーションベースの課税方式が異なる地域で混乱しやすい。日本国内のオンラインショップでは基本的に配送先住所の税率(消費税10%または軽減税率8%)が使われるべきだが、WooCommerce Tax が海外の課税ロジックを引きずっている場合もあり、実際に「店舗住所を変えると税率が変わってしまう」といった現象が報告されている。
配送先住所「大阪市 530-0001」(税率8.25%のはず)
↓
適用される税率 → 店舗住所「東京都 100-0001」の税率10%
配送先住所「大阪市 530-0001」
↓
適用される税率 → 配送先住所の8.25%
このデモのように、配送先住所を正しく入力していても、店舗住所の税率だけが繰り返し使われるのが典型的な症状だ。
税計算の基準が本当に配送先住所になっているか再確認する

まず根本的な設定ミスがないか、管理画面をチェックする。
設定画面上は正しく見えていても、内部的に値がロックされている場合がある。STEP 3 のように一度無効化して再保存することで、WooCommerce Tax の内部キャッシュをリセットできる。
トランジェントキャッシュを手動で削除する
WooCommerce Tax は API から取得した税率データを WordPress のトランジェント(一時キャッシュ)に保存している。このキャッシュが古いままだと、配送先住所が変わっても最初に引いた店舗住所のレートを返し続けることがある。
データベースを直接操作せずにキャッシュをクリアする方法
- WooCommerce > ステータス > ツール に移動する
- 「WooCommerce トランジェントをクリア」を実行する
- さらに「顧客セッションをクリア」も実施する
- 必要に応じて、WooCommerce Tax プラグインを無効化してから削除し、再度インストールして有効化する
再インストール時には、プラグインが新しい API キーを取得し、税設定が初期化される。その後、必ず「WooCommerce > 設定 > 税」で「配送先住所に基づいて計算する」を再設定する。
配送先住所の受け渡しをデバッグモードで検証する

テーマや他のプラグインの影響で、チェックアウト画面から正しい配送先住所が WooCommerce Tax に渡っていない可能性もある。WooCommerce のデバッグモードを有効にして、税計算の内部ログを確認する。
define('WP_DEBUG', true); を追加WooCommerce > ステータス > ログ に、woocommerce-tax や taxjar のログファイルが生成される。配送先住所ではなく店舗住所が送信されているようであれば、テーマの functions.php やカスタムコードが住所情報を改変していないか精査する。
応急的に店舗住所を「配送先住所」と同じ扱いにするフィルター
どうしても自動税計算が配送先住所を認識せず、緊急で正しい税率を適用しなければならない場合、WordPress のフィルターフックを使って一時的に配送先住所を強制的に税計算に使わせることもできる。
add_filter( 'woocommerce_tax_based_on', function( $base ) {
if ( is_checkout() || is_cart() ) {
return 'shipping';
}
return $base;
});このコードを子テーマの functions.php に追加すれば、カート・チェックアウト画面では常に配送先住所ベースの計算が強制される。ただし、根本原因の解決にはならないため、あくまで応急策として利用する。
よくある質問

WooCommerce Tax を再インストールしても直らないのはなぜか
再インストールだけでは、データベースに残ったトランジェントや設定値が削除されないことがある。プラグインを削除した後に「WooCommerce > ステータス > ツール」からトランジェントを完全クリアし、その上で再インストールする必要がある。
配送先住所が正しく入力されているのに税率が変わらないのはどうしてか
WooCommerce Tax は TaxJar API に配送先の ZIP コードと国・州の情報を送り、税率を取得する。このとき、ZIP コードが実在しないか API が認識できない場合、フォールバックとして店舗住所の税率を返す仕様がある。テストする住所が実在するか、郵便番号のフォーマットが正しいかを再確認する。
WooCommerce Tax を使わずに日本国内の税率を正確に計算するにはどうすればよいか
日本国内のオンラインショップで消費税のみを扱うなら、自動税率プラグインを無効化し、WooCommerce 標準の税率設定で「標準税率(10%)」と「軽減税率(8%)」を手動で登録する方が安定する。配送先住所の県や市町村による税率差分が不要なケースが大半のため、あえて自動計算を導入する必要はない。
テスト注文を何度も行っても税額が変わらない場合の最終確認事項は
テスト注文時には、必ずブラウザのシークレットウィンドウを使い、サイトのキャッシュやセッションの影響を排除する。また、カートの計算がセッション情報に依存するため、住所を変えるたびにカートを空にしてから再度商品を追加する。
特定の州や地域でオリジンベース課税のせいで税率が店舗住所になることはあるのか
米国の一部の州では、店舗所在地と配送先の両方が同じ州内にある場合、店舗所在地の税率を適用するオリジンベース課税が採用されている。しかし、WooCommerce Tax は州ごとの課税方式を自動で判別するわけではなく、設定上のトラブルでこの現象が起こることがある。日本のショップでは関係ないが、海外向けに販売する場合は注意が必要だ。
この記事のポイント
- 自動税計算が配送先住所を無視するのは、設定キャッシュか住所の受け渡し不良が主な原因
- 「WooCommerce > 設定 > 税」の計算基準を再確認し、無効化→再有効化で内部リセットを試す
- トランジェントキャッシュを手動クリアし、必要ならプラグインの再インストールを行う
- デバッグログで TaxJar API へのリクエスト内容を検証する
- 日本国内のみのショップなら自動税率をやめ、標準税率を手動設定する方が安定する

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

Booking Calendar更新後にサイトが壊れた時の原因と直し方
Booking Calendar プラグインを 11.4.1 から 11.4.2 へ更新した直後にサイトが壊れた場合、無料版(Booking Calendar)と有料版(Booking Calendar Pro または Booking Manager)のバージョン不一致が主要因だ。手動で両方を同一の最新バージョンに揃え、かつ Pro 版のライセンスを再適用すれば復旧できる。
なぜバージョン 11.4.2 への更新でサイトが壊れたのか

Booking Calendar は無料版(WordPress.org 配布)と、追加機能を提供する Pro 版(開発元サイトで購入)が連携して動作する設計になっている。無料版は管理画面の「プラグイン」から自動更新される一方、Pro 版は手動で更新する必要がある。両者のバージョンが食い違うと、共有する関数やデータベース構造に不整合が生じ、PHP の致命的エラーを引き起こして画面が表示されなくなる。
とくに 11.4.2 では内部 API の変更が加えられており、Pro 版が旧バージョンのまま無料版だけを更新すると競合が起きやすい。この状態で WordPress の「このサイトで重大なエラーが発生しました」というメッセージが表示されたり、管理画面にアクセスできなくなったりする。
サイトを元に戻す具体的な手順

以下の手順で、無料版と Pro 版を安全に最新へ揃える。作業前に必ずサイト全体のバックアップを取得しておく。
/wp-content/plugins/ にアクセスするbooking → booking_old)プラグインフォルダを特定して無効化する
サイトが壊れて管理画面に入れない場合は、FTP(File Transfer Protocol)クライアントやレンタルサーバーのファイルマネージャを使う。/wp-content/plugins/ ディレクトリ内に、無料版(通常は booking または booking-calendar)と Pro 版(booking-calendar-pro や wpdev-booking など)のフォルダが存在する。両方をリネームすれば、WordPress はプラグインを強制的に無効化し、サイトが最低限の状態で表示されるようになる。リネーム後のフォルダ名は削除せず控えておく。
無料版を最新にして Pro 版を再適用する
管理画面にアクセスできる状態になったら、プラグイン一覧画面で一度 Booking Calendar を削除する。削除しても予約データはデータベースに保持されるため、消えることはない。その後「新規追加」から再度 Booking Calendar 11.4.2 をインストールし有効化する。
続いて開発元サイト(wpbookingcalendar.com)のアカウントページから、無料版と同一バージョン(11.4.2)に対応した Pro 版の ZIP ファイルをダウンロードする。管理画面の「プラグイン」→「新規追加」→「プラグインのアップロード」から ZIP を投入し、有効化後にライセンスキーを入力すれば復旧が完了する。Pro 版の最新ファイルが入手できない場合は、開発元のサポートへ直接更新ファイルを依頼する。
どうしても復旧できない場合の最終手段
Pro 版の最新 ZIP が手元になく、サイトのダウンタイムが許容できない状況では、無料版を旧バージョン(11.4.1)にダウングレードする選択肢もある。WordPress.org のプラグインページにある「以前のバージョン」から 11.4.1 の ZIP を入手し、FTP で手動上書きすれば以前の動作に戻せる。ただしセキュリティ修正が含まれている可能性があるため、この状態は恒久的な対策にはならず、早期に Pro 版を最新化する必要がある。
再発を防ぐための運用ルール

Booking Calendar のように無料版と有料版が連動するプラグインは、無料版の自動更新をオフにするか、更新前に必ず Pro 版の対応バージョンがリリースされているかを確認する習慣をつける。開発元のチェンジログやメーリングリストを購読しておくと、更新のタイミングを逃さない。
また本番環境に直接適用する前に、ステージング環境(本番と同一構成のテストサイト)で無料版と Pro 版の同時更新を試すのが最も確実な予防策になる。レンタルサーバーのステージング機能を使うか、WP Staging のようなプラグインで簡易的なテスト環境を用意できる。
よくある質問
Pro 版の最新ファイルがアカウントページに見当たらない場合はどうすればよいか
開発元の公式サイトにある問い合わせフォームまたはサポートチケットから、Pro 版の最新 ZIP ファイルを直接依頼する。購入時のメールアドレスやライセンスキーを記載すれば、通常は数営業日以内にダウンロードリンクが提供される。
フォルダをリネームしたがサイトがまだ壊れている
キャッシュ系プラグインや CDN(コンテンツデリバリネットワーク / 配信網)が古いエラー画面を配信し続けている可能性がある。サーバー側のキャッシュをすべてクリアし、ブラウザのシークレットモードで確認する。また wp-content/mu-plugins/ に手動で入れたファイルが競合していないかも調べる。
ライセンスキーを入力しても Pro 版の機能が有効にならない
ライセンスキーが旧バージョン向けのまま失効している可能性がある。開発元のマイページでキーを再発行するか、サポートにキーのリセットを依頼する。ドメインを変更した場合もライセンスの再割り当てが必要になる場合がある。
この記事のポイント
- Booking Calendar 11.4.1 から 11.4.2 への更新障害は無料版と Pro 版のバージョン競合が原因
- FTP で両方のプラグインフォルダをリネームし強制無効化して管理画面へ復帰
- 無料版は削除後に 11.4.2 を再インストール、Pro 版は開発元から同一バージョンを入手
- Pro 版がすぐ用意できない場合は無料版のみ旧バージョン 11.4.1 に戻す応急処置も可能
- 再発防止には無料版の自動更新を止め、Pro 版のリリース確認後に揃えて更新する

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WordPressをサブフォルダにインストールするとREST APIが404になる原因と直し方
WordPressをサブフォルダにインストールしている環境で、REST APIのエンドポイントが404エラーを返す場合は、プラグインがサブフォルダを考慮せずにAPIのURLを生成しているバグが原因だ。該当プラグインを最新版に更新するか、パーマリンク設定のリフレッシュで解決する。
なぜサブフォルダ環境でプラグインのAPIが404になるのか

WordPressをドキュメントルート直下ではなく/blogや/siteのようなサブフォルダにインストールした場合、REST APIのベースURLはhttps://example.com/subfolder/wp-json/となる必要がある。ところが一部のプラグインは、内部でAPIのURLを組み立てる際にこのサブフォルダを考慮しておらず、https://example.com/wp-json/...のようにルート直下を指してしまう。その結果、実在しないパスへのリクエストとなり404が返る。
今回のケースでは、プラグインが独自に追加したエンドポイント/profeedwp/v1/linkedin/company-posts/smartに対して、サブフォルダを含まない不完全なURLでリクエストを発行していた。同様の問題は、テーマや他のプラグインがrest_url()関数を正しく使わずにハードコードしたパスを参照している場合にも起こる。
解決手順

まず簡単かつ即効性のある方法として、問題のプラグインを最新版へ更新する。次に、WordPressのパーマリンク設定をリセットし、REST APIのルートURLが正しく再構築されるか確認する。これで直らない場合は、手動でrest_url()が返す値を検証し、他のプラグインとの競合を調べる。
プラグインを最新版に更新する
本件ではバージョン1.6.10で修正が行われている。管理画面の「プラグイン」→「インストール済みプラグイン」から対象プラグインを確認し、更新が表示されていれば適用する。更新が出ていない場合は、一度プラグインを削除して再インストールするか、開発元の公式ページから修正版がリリースされていないか確認する。
パーマリンク設定をリセットする
プラグインの更新で直らなかった場合、パーマリンク構造の再保存でWordPress内部のルーティングをリフレッシュできる。「設定」→「パーマリンク」を開き、現在選択されている設定をそのままの状態で「変更を保存」をクリックする。これにより.htaccessの再生成と、REST APIのルート定義が再構築される。サブフォルダ環境では特に、リライトルールが正しくサブフォルダをプレフィックスとして含む必要があるため、この一手順で解決するケースが多い。
rest_url() の戻り値を検証する
根本原因がプラグイン側のURL組み立てにあるかどうかを切り分けるには、WordPressが正しいREST APIのルートURLを返しているかを確認する。テーマのfunctions.phpなどに次のようなテストコードを一時的に追加する。
add_action('wp_footer', function() {
echo '<!-- REST URL: ' . esc_url(rest_url()) . ' -->';
});サイトのフッター部分のHTMLソースに出力されたURLがhttps://example.com/subfolder/wp-json/の形式になっていれば、WordPress本体の認識は正しい。もし/subfolderが欠落している場合は、wp-config.phpでWP_HOMEとWP_SITEURLが正しくサブフォルダを含んだ値で定義されているか確認する。
全プラグインを無効化して競合を切り分ける
それでも404が解消しない場合、別のプラグインがREST APIのルーティングに干渉している可能性がある。すべてのプラグインを一括で無効化し、問題のエンドポイントにアクセスして200番台のレスポンスが返るかテストする。正常動作が確認できたら、プラグインを1つずつ有効化して原因のプラグインを特定する。キャッシュ系プラグインやセキュリティプラグインは、REST APIへのリクエストをブロックしたり、URLを書き換えたりする設定項目を持つことがあるため、該当するプラグインの設定もあわせて確認する。
よくある質問
サブフォルダにインストールする際にwp-config.phpで注意すべき点は?
WP_HOMEとWP_SITEURLの定数をhttps://example.com/subfolderのようにサブフォルダを含めて明示的に定義しておくと、サイトURLの誤認識を防げる。wp-config.phpに記述しなければならないわけではないが、マルチサーバー構成やリバースプロキシの背後で運用する場合は特に有効だ。
REST APIの404エラーはどのようにデバッグすればいいか?
ブラウザのデベロッパーツールのネットワークタブで、実際に送信されたリクエストURLを確認する。サブフォルダが欠落したURLでリクエストが発生している場合は、呼び出し元のJavaScriptファイルやPHPコードでURLの組み立て方をチェックする。rest_url()を使わずにハードコードされたパスが原因であることが多い。
プラグインを更新しても問題が再発する場合は?
修正パッチが適用されたバージョンでも、キャッシュの残存やデータベースに保存された古い設定値が原因で再発することがある。プラグインを完全に削除したあと、wp_optionsテーブルに残っている該当プラグインのオプションを手動で削除し、最新版を再インストールすると改善する場合がある。
サブフォルダ環境でなくてもAPIが404になる原因は?
パーマリンク設定が「基本」になっているとREST APIが動作しない。また、セキュリティプラグインが/wp-json/へのアクセスを制限しているケースもある。.htaccessのリライトルールが破損している場合も404になるため、パーマリンク設定の再保存でリフレッシュするのが初手として有効だ。
この記事のポイント
- サブフォルダ環境でプラグインのAPIが404になるのは、URLにサブフォルダが含まれない不完全なパスが原因
- 問題のプラグインを最新版に更新し、パーマリンク設定を再保存するのが解決の基本手順
- rest_url() の戻り値とwp-config.phpの設定を確認し、WordPress本体のURL認識が正しいか検証する
- 全プラグインの無効化で競合を切り分け、キャッシュやセキュリティ系プラグインの干渉を疑う

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

Gravity Forms PDFで合計金額が倍になる原因と修正方法
Gravity Forms で作成したフォームから PDF を出力するプラグイン「PDF Invoices for Gravity Forms」を使っていて、テンプレート内で get_total() メソッドを複数回呼び出すと合計金額が呼び出し回数に応じて倍々に膨らんでしまう現象は、静的変数 self::$total が各呼び出しのたびに加算され続ける設計になっているのが原因だ。直すにはヘルパークラスを子テーマから拡張し、get_total() の内部で毎回リセットして再計算させる変更を加える。
合計金額が倍になる現象はどのようなときに起こるのか

たとえば請求書のテンプレートに「小計」と「総合計」を別々の位置に表示したい場合、PDF_Invoices_For_GravityForms_Helpers::get_total() を2回呼ぶことになる。ところがイベント参加登録や商品注文フォームなどで実際にこの処理を通すと、2回目の呼び出し時には1回目に加算された値にさらに同じ計算が上乗せされ、本来 10,000 円のところが 20,000 円になるといった不具合が起きる。
なぜ get_total() を複数回呼ぶと値が積み上がるのか

問題の根本は class-pcafe-gfpi-helpers.php ファイル内の get_total() メソッドにある。このメソッドは静的変数 self::$total を使い、内部で次のように加算している。
public static function get_total(){
self::$total += self::get_subtotal();
self::$total += self::$shipping;
return self::$total;
}静的変数はリクエストの間ずっと値を保持するため、同じ処理中に get_total() が呼ばれるたびに前回の合計に小計と送料が足されていく。2回呼べば「小計 + 送料」が2倍になり、3回なら3倍になる。通常、こうした合計取得メソッドは毎回ゼロから計算し直すべきであり、内部で継ぎ足す構造は意図したものでない可能性が高い。
変数 self::$total が 10,500 を保持したまま
2回目呼び出し: 変数をリセット後 再計算 → total=10,500
上の図のように、2回目で合計が倍になる。特に「小計」「消費税」「総合計」など複数の金額を PDF テンプレートに配置する場合にこの問題が顕在化しやすい。
get_total() 修正の基本的な考え方

プラグイン本体のファイルを直接編集してしまうと、アップデートのたびに修正が上書きされて消える。そのため子テーマの functions.php を使い、プラグインのヘルパークラスを拡張した独自クラスを用意する方法をとる。拡張クラスでは get_total() メソッドをオーバーライドし、計算前に self::$total を強制的に 0 にリセットしてから小計と送料を加算する。
子テーマでヘルパークラスを拡張して修正する手順

独自ヘルパークラスを作成する
まず子テーマの functions.php に、プラグインのヘルパークラスを継承したクラスを定義する。子テーマがない場合は、Code Snippets プラグインを使うか、wp-content/themes/(現在のテーマ)/functions.php に追記する形でもよい。コードは以下のようになる。
class Custom_GFPI_Helpers extends PDF_Invoices_For_GravityForms_Helpers {
public static function get_total() {
self::$total = 0; // 計算前に必ずリセットする
self::$total += self::get_subtotal();
self::$total += self::$shipping;
return self::$total;
}
}テンプレート内でカスタムクラスを呼び出す
拡張クラスを作っただけでは既存のテンプレートには反映されない。PDF テンプレート内で PDF_Invoices_For_GravityForms_Helpers::get_total() を呼んでいる箇所を、先ほど定義した Custom_GFPI_Helpers::get_total() に置き換える。
テンプレートファイルは多くの場合 wp-content/uploads/pdf-invoices-for-gravity-forms/templates/ 以下にカスタムテンプレートとして配置されている。該当の .php ファイルを開き、以下のように書き換える。
<?php
// 修正前
// echo PDF_Invoices_For_GravityForms_Helpers::get_total();
// 修正後
echo Custom_GFPI_Helpers::get_total();
?>これでテンプレート内のどの場所から呼び出しても、毎回リセット後に計算が走るため合計が積み上がることはなくなる。
変更後にキャッシュと動作を確認する
変更を加えたあとは、必ず PDF を生成し直して合計金額が正しいか確認する。Gravity Forms のエントリーから「PDFを表示」ボタンで実際の請求書を開き、同じ合計が要求された位置すべてに正しく表示されているかをチェックする。サイトでキャッシュプラグインを使っている場合は、キャッシュを全削除してから確認すると確実だ。
よくある質問
プラグイン本体のファイルを直接修正してもよいか
推奨しない。プラグインがアップデートされるたびに修正が上書きされ、その都度同じ変更を加えなければならなくなる。子テーマや Code Snippets を使う方法なら、アップデートに影響されず継続的に動作する。
他の金額表示(税額や値引き額)も倍増している場合の対処は
同じヘルパークラス内で定義されている get_tax() や get_discount() にも同様の静的変数の加算構造がある可能性が高い。それらのメソッドも同じ要領でカスタムクラス内にオーバーライドし、内部で該当の静的変数をリセットする処理を加えるとよい。
子テーマを使っていない場合でも対応できるか
子テーマがない場合は Code Snippets プラグインが便利だ。スニペットとしてクラス定義を追加すれば、テーマに依存せず同じ修正を適用できる。テンプレートの書き換えは手動で行う必要があるが、クラスの読み込み自体はスニペット経由で問題なく動作する。
修正後に PDF が真っ白になる場合の確認点は
クラス名やメソッド名のスペルミス、オートローダーがカスタムクラスを見つけられていないケースが考えられる。まず PHP のエラーログを確認し、クラスが見つからないという趣旨の致命的エラーが出ていないか調べる。出ている場合はクラス定義の記述ミスか、定義のタイミングが早すぎる可能性があるため、init フックなどで定義を遅らせると改善することがある。
この記事のポイント
get_total()の多重呼び出しで合計が倍増するのは、静的変数self::$totalが加算され続ける設計のため- プラグイン本体を直接修正せず、子テーマの functions.php でカスタムクラスを定義する
- カスタムクラス内で
get_total()をオーバーライドし、計算前にself::$total = 0;でリセットする - PDF テンプレート側の呼び出しをカスタムクラスに差し替え、キャッシュ削除後に動作確認する
- 同様の構造を持つ
get_tax()やget_discount()も併せて修正を検討する

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WordPress 7.0.1でクラシックエディタ保存できない時の原因と直し方
WordPress 7.0.1 更新後にクラシックエディタや WPBakery などのページビルダーで投稿や固定ページを保存できない、下書きが消えるといった症状は、PHP 8.4 との互換性問題が原因だ。PHP バージョンを 8.3 以下に切り替えればこの問題は解消する。
クラシックエディタで保存できずリダイレクトされる現象の正体

WordPress 7.0.1 に更新した直後から、クラシックエディタプラグインを有効化していると「公開」「下書き保存」をクリックしても保存されず、投稿一覧にリダイレクトされてしまう。保存したはずの記事や固定ページは一覧からも消え、下書きにも残らない。
さらにややこしいのは、ブロックエディタ(Gutenberg)では問題なく保存できるという点だ。クラシックエディタのプラグインを無効化せずとも、ブロックエディタ側で開いて操作すれば保存は成功する。このため一見すると「特定のプラグインだけが壊れている」ように見えるが、実際にはクラシックエディタ系や WPBakery など旧来の編集画面に依存するツール全般で同じ症状が出る。
この現象はプラグイン側の不具合ではなく、WordPress コアが動作する PHP のバージョンに起因する。特に PHP 8.4 環境で顕在化しやすい。
なぜ PHP 8.4 でクラシックエディタが動作しなくなるのか

根本原因は PHP 8.4 で廃止または挙動が変更された関数や構文が、クラシックエディタの編集画面や保存処理の中で使われていることにある。古いエディタ画面は WordPress コアの一部として動作するが、その内部処理が新しい PHP の厳格な型チェックや廃止予定の警告(Deprecated)に引っかかり、画面遷移やデータ保存に失敗する。
たとえば、PHP 8.4 では暗黙の nullable 型宣言が非推奨になり、引数のデフォルト値や型宣言の扱いが厳密化された。WordPress の管理画面まわりには長い歴史を持つコードが多く、こうした細かな PHP の変更に対してすべてのプラグインやテーマが追随できているわけではない。
ブロックエディタが正常に動作するのは、ブロックエディタの保存処理が REST API を経由し、比較的新しいコードベースで実装されているため、PHP 8.4 の影響を受けにくいからだ。
PHP バージョンを 8.3 に切り替えて問題を解消する

現時点で最も確実な対処法は、サーバーの PHP バージョンを 8.3 にダウングレードすることだ。PHP 8.4 はリリースされたばかりで、WordPress エコシステム全体の完全な互換性が確保されるまでは安定動作が見込める 8.3 を使うほうが無難である。
クラシックエディタ保存不可 → 一覧にリダイレクト → 記事消失
クラシックエディタ正常保存・下書きも残る
多くのレンタルサーバーではコントロールパネル(cPanel や独自管理画面)から簡単に PHP バージョンを切り替えられる。
サーバー管理画面での具体的な操作
cPanel を使っている場合は「PHP の選択」または「MultiPHP Manager」といったメニューを探す。対象ドメインを選択し、ドロップダウンメニューから「PHP 8.3」を選んで保存するだけだ。変更は数分以内に反映される。
独自の管理画面を提供しているサーバーでも、多くの場合「PHP 設定」「PHP バージョン管理」といった項目がある。もし見つからなければサーバー運営会社のサポートに「PHP バージョンを 8.3 に変更したい」と伝えれば対応してくれるケースが多い。
変更前に現在の PHP バージョンを確認する
WordPress 管理画面の「ツール」→「サイトヘルス」→「情報」タブを開き、「サーバー」セクションを見ると現在の PHP バージョンが表示されている。ここで 8.4 以上であれば今回の問題に該当する可能性が高い。
PHP 8.3 への切り替えでも直らない場合の追加確認

ごくまれに、PHP バージョンを下げても問題が続くことがある。そんなときは次の3点を順に確かめる。
ブラウザキャッシュと WordPress キャッシュのクリア
PHP の変更後にブラウザのキャッシュが残っていると、古い JavaScript や CSS で画面が正しく動作しないことがある。ブラウザのキャッシュを削除するか、シークレットウィンドウで管理画面を開き直す。また、WordPress 側でキャッシュプラグインを使っている場合はそのキャッシュもすべて削除する。
管理画面で JavaScript エラーが出ていないか調べる
ブラウザの開発者ツール(F12 キー)を開き、「コンソール」タブで赤いエラーが出ていないか確認する。保存ボタンを押した瞬間に何らかの JavaScript エラーが記録されていれば、それが原因の手がかりになる。
WordPress のデバッグモードでログを取得する
wp-config.php に以下のコードを追加してデバッグモードを有効にすると、保存時のエラーが wp-content/debug.log に記録される。
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);ログに「Deprecated」や「Fatal error」が記録されていれば、それが直接の原因を示している。ただし、大半のケースでは PHP 8.3 への切り替えだけで問題が解消するため、ログを調べるのはレアケースの最終手段と考えてよい。
よくある質問
PHP 8.3 に戻すとセキュリティ面で問題はないか
PHP 8.3 は現在もアクティブサポートが継続しており、セキュリティ修正は提供され続けている。WordPress 公式の推奨バージョンでもあるため、本番環境で使っても安全だ。無理に最新の 8.4 に上げるよりも、安定した 8.3 で運用するほうが結果的にリスクが低い。
PHP 8.3 に変更したのにクラシックエディタがまだ使えない
PHP の変更がサーバーに完全に反映されるまで数分かかることがある。まずは数分待ってから再度試す。それでも改善しない場合は、一度プラグインを無効化して再度有効化してみる。また、前述のキャッシュクリアも忘れずに行う。
WPBakery や他のページビルダーでも同じ症状が出るのか
出る。クラシックエディタだけでなく、WPBakery をはじめとする旧型の編集画面を使うページビルダー全般が PHP 8.4 の影響を受ける。これらもブロックエディタと異なり、内部の保存処理が古いコードに依存しているためだ。
PHP バージョンを自由に変更できないサーバーではどうすればいいか
サーバー管理画面に PHP バージョンの変更オプションがない場合は、サーバー運営会社のサポートに連絡して「PHP 8.3 への切り替えを依頼したい」と伝える。ほとんどの会社は対応してくれる。もし変更ができないと言われた場合は、PHP 8.4 の環境でも動作するように WordPress のアップデートを待つか、ブロックエディタに一時的に切り替えて運用するしかない。
この記事のポイント
- WordPress 7.0.1 でクラシックエディタ保存不可になる原因は PHP 8.4 の互換性問題
- PHP バージョンを 8.3 に下げると問題は即座に解消する
- ブロックエディタは PHP 8.4 でも正常に動作するため一時的な回避策になる
- 変更後はブラウザキャッシュと WordPress キャッシュを忘れずにクリアする
- PHP 8.3 は公式推奨でありセキュリティ面でも安全に運用できる

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

データベース接続確立エラーの原因と復旧手順
「データベース接続確立エラー」でサイトがダウンした場合、まずはサーバー会社に連絡してデータベースサーバーの稼働状況を確認し、wp-config.php の接続情報を照合するのが最短の復旧手順だ。自分でできる対処は限られているため、慌てずに切り分けを進める。
なぜ「データベース接続確立エラー」が突然発生するのか

このエラーは WordPress がデータベースに接続できないときに表示される。日本語環境では「データベース接続確立エラー」というメッセージが画面に表示され、サイト全体が表示できなくなる。原因は大きく4つに分けられる。
- wp-config.php 内のデータベース名・ユーザー名・パスワード・ホスト名のいずれかが誤っている
- データベースサーバー自体がダウンしている(サーバー障害・メンテナンス)
- データベースサーバーは稼働しているが、負荷集中で応答不能になっている
- データベースが破損している(テーブルクラッシュなど)
サイトを長期間触っていなかったのに突然エラーが出た場合は、サーバー側で MySQL や MariaDB のバージョンアップ、パスワード変更、セキュリティ設定の変更が行われた可能性が高い。WordPress 側の設定ファイルは変わらないまま、サーバー側の接続条件だけが変わることで不一致が起きる。
wp-config.php とデータベースの認証情報が不一致、または DB サーバーが停止
正しい接続情報で WordPress がデータベースにアクセスできる状態
エラーが出たらまず試す3つの切り分け

サーバー会社にデータベースサーバーの状態を問い合わせる
最も確実で早いのが、利用しているサーバー会社のサポートに連絡することだ。データベースサーバーがダウンしていれば、自分で何をしても復旧しない。管理画面にログインできなくても、サーバー会社のコントロールパネル(cPanel や独自管理画面)にアクセスできれば、そこからデータベースの状態を確認できる場合もある。
特に共有サーバー(複数ユーザーで1台のサーバーを共有するプラン)では、他のユーザーの影響でデータベースサーバーに負荷がかかり、一時的に応答しなくなることがある。この場合もサーバー会社側で対処が必要になる。
wp-config.php の接続情報を確認する
FTP ソフトやサーバーのファイルマネージャーで WordPress のインストールディレクトリにある wp-config.php を開き、以下の4つの定数を確認する。
define( 'DB_NAME', 'database_name_here' );
define( 'DB_USER', 'username_here' );
define( 'DB_PASSWORD', 'password_here' );
define( 'DB_HOST', 'localhost' );これらの値がサーバーのデータベース管理画面(phpMyAdmin やサーバー会社のコントロールパネル)で設定した値と完全に一致しているか確認する。サーバー会社がパスワードをリセットした場合や、セキュリティアップデートでホスト名が localhost から mysqlcluster2.example.com のような専用ホスト名に変更されるケースがある。
wp-config.php に一時的な確認コードを入れる
接続情報が正しいかどうかを切り分けるには、wp-config.php に以下のテストコードを追加する方法も有効だ。エラーメッセージの詳細が表示され、単なる認証エラーなのか、サーバー自体に到達できないのかが判別できる。
$link = mysqli_connect( DB_HOST, DB_USER, DB_PASSWORD, DB_NAME );
if ( ! $link ) {
die( '接続失敗: ' . mysqli_connect_error() );
}
echo '接続成功';
die();このコードを wp-config.php の /* That's all, stop editing! Happy blogging. */ より上に追記し、サイトにアクセスする。「接続失敗」と表示されれば認証情報かサーバー到達性の問題、「接続成功」と表示されれば WordPress 本体やプラグイン側の別の要因が疑われる。確認が終わったら必ずこのコードを削除する。
phpMyAdmin からデータベースに直接接続する
サーバー会社のコントロールパネルから phpMyAdmin にアクセスし、該当のデータベースを開けるか確認する。開ければ、データベースサーバーは稼働しており、認証情報も正しいことがわかる。開けない場合は、ユーザー名・パスワードが誤っているか、そのユーザーにデータベースへのアクセス権限が付与されていない。
phpMyAdmin 自体が開けない、または読み込みに極端に時間がかかる場合は、データベースサーバーの高負荷やダウンが原因だ。この場合もサーバー会社への連絡が必要になる。
データベースの修復が必要なケース

wp-config.php の情報が正しく、データベースサーバーも稼働しているのに接続エラーが出る場合、データベースのテーブルが破損している可能性がある。この修復は WordPress の自動修復機能で対応できる。
wp-config.php に以下の1行を追加する。
define( 'WP_ALLOW_REPAIR', true );その後、ブラウザで https://あなたのサイトのURL/wp-admin/maint/repair.php にアクセスすると、データベース修復画面が表示される。「データベースを修復」または「データベースを修復して最適化」ボタンをクリックすれば修復が実行される。修復完了後は、セキュリティのために必ず追加した行を削除する。
管理画面にログインできない場合の対処

「データベース接続確立エラー」が出ている間は、WordPress の管理画面(/wp-admin)にもアクセスできない。この状態では wp-config.php の確認や修正を WordPress の管理画面から行うことはできず、必ずサーバー側のファイルマネージャーか FTP ソフトを使う必要がある。
FTP の接続情報がわからない場合も、サーバー会社のサポートに連絡すれば、コントロールパネルへのログイン方法やファイルマネージャーの使い方を案内してもらえる。WordPress のログイン情報よりも先に、サーバーの管理画面にアクセスできる状態を確保することが復旧の第一歩だ。
再発を防ぐための日常的な対策

データベース接続エラーは突然発生し、サイト全体が完全に停止するため、予防と早期発見の仕組みを整えておくことが重要だ。
- サーバー会社のデータベース稼働状況を定期的にチェックする(障害通知メールの設定)
- データベースの定期バックアップを自動化する(サーバー側のバックアップ機能やプラグインを利用)
- wp-config.php のバックアップを手元に保管し、接続情報をメモしておく
- サーバー会社のコントロールパネルと FTP のログイン情報を常に最新に保つ
特にレンタルサーバーの共有プランを利用している場合、サーバー会社がメンテナンスやセキュリティアップデートでデータベースの接続設定を変更することがある。変更の予告メールを見逃さないよう、サーバー会社からのメールは確実に受信できるアドレスに設定しておく。
よくある質問
データベース接続エラーと「重大なエラー」は別のものか
別のエラーだ。「データベース接続確立エラー」はデータベースとの通信そのものができない状態で、サイト全体が表示されない。「このサイトで重大なエラーが発生しました」は WordPress 本体やプラグインの PHP エラーで、管理画面にメールが届く場合もある。後者はデータベースに接続できていることが前提になる。
wp-config.php を修正したのに直らない場合はどうすればよいか
データベースサーバー自体が停止しているか、MySQL のサービスが落ちている可能性が高い。サーバー会社のコントロールパネルで MySQL の状態を確認し、停止していれば再起動を試みる。操作権限がない場合はサーバー会社に依頼する。
データベースのユーザー名やパスワードを忘れた場合はどうするか
サーバーのコントロールパネル(cPanel の「MySQL データベース」など)から確認または再設定できる。WordPress の管理画面からは確認できないため、必ずサーバー側の管理画面を使う。パスワードをリセットした場合は、wp-config.php の DB_PASSWORD も新しい値に更新する必要がある。
データベースの修復でデータが消えることはあるか
WP_ALLOW_REPAIR による修復は、破損したテーブルの構造を修復する機能で、保存されている投稿や設定データを削除することはない。ただし、修復作業の前には必ずデータベースのバックアップを取得しておくことが望ましい。
エラーが断続的に発生する場合の原因は何か
データベースサーバーの負荷が一時的に高まっているか、同時接続数の上限に達している可能性がある。アクセス集中時だけエラーが出る場合は、サーバースペックやプランの見直しを検討する。また、プラグインが非効率なデータベースクエリを大量に発行していないかも確認する。
この記事のポイント
- データベース接続エラーは wp-config.php の誤りかサーバー側の障害が主因
- エラー発生時は管理画面にログインできないため、FTP やサーバー管理画面で対応する
- サーバー会社に連絡してデータベースサーバーの稼働状態を確認するのが最短の復旧手段
- テーブル破損が疑われる場合は WP_ALLOW_REPAIR で修復を試みる
- 日常的にバックアップと接続情報の控えを取っておくことで復旧時間を短縮できる

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

WordPress会員データが大量削除された時の原因と復旧手順
WordPress サイトで会員データが突然数千件単位で削除され、WP Activity Log に「Unknown user」として記録される事態は、データベースへの直接アクセスか管理者権限の乗っ取りによる攻撃の可能性が高い。即座にサイトをメンテナンスモードに切り替え、被害拡大を防ぎつつバックアップから復旧し、侵入経路を特定して再発を防ぐ必要がある。
なぜ突然会員データが大量削除されたのか
この事象の最大の特徴は、削除を実行したユーザーが「Unknown user」と表示される点にある。通常、WordPress の操作ログにはユーザー名かユーザー ID が記録されるが、ここに名前が出ないということは、wp_users テーブルを経由しない削除が行われていることを示している。考えられる原因は大きく3つに絞られる。
データベースへの直接操作
最も深刻なケースとして、攻撃者が SQL インジェクションや phpMyAdmin への不正アクセス、あるいはサーバーに仕込んだマルウェア経由でデータベースに直接 DELETE 文を実行している状況だ。この場合、WordPress のアクションやフィルターフックを一切通過しないため、WP Activity Log を含むどの監査プラグインもユーザーを特定できず「Unknown」となる。
管理者アカウントの乗っ取り
管理者権限を持つアカウントが乗っ取られ、攻撃者がそのアカウントで MemberPress の会員一括操作機能やデータベースクリーニング系プラグインを実行したケースだ。ただし、この場合は通常ユーザー名がログに残る。残っていないということは、攻撃者が操作後にユーザーごと削除したか、別の手段を使った可能性が高い。
REST API や XML-RPC の悪用
WordPress の REST API や XML-RPC に認証の弱点があると、外部から会員データの削除リクエストを送信される場合がある。特に、API 経由で直接データベース操作を行うカスタムエンドポイントがテーマやプラグインに存在すると、認証をすり抜けて大量削除が実行される危険がある。
同時に多数のプラグイン更新が表示され、WordPress 7.0.1 への更新も同日にリリースされたという状況は、実際に重大な脆弱性が公表され、各開発者が一斉にパッチを配布している可能性を示唆している。更新が突如10件以上積み上がるのは、テーマやプラグインに含まれる共通ライブラリに脆弱性が見つかった場合によく見られるパターンだ。
攻撃を受けた直後にとるべき緊急対応の手順

被害の発覚から時間が経つほど、データ消失や情報流出の範囲は広がる。以下の手順を発見後30分以内に実行することで、二次被害を最小限に抑えられる。
メンテナンスモードでアクセスを遮断する
まず、攻撃が継続している可能性を想定し、サイト全体をメンテナンスモードに切り替える。管理画面にアクセスできる状態であれば、.maintenance ファイルを手動で作成する方法が最も確実だ。WordPress のルートディレクトリに .maintenance ファイルを配置し、以下の内容を記述すると、全訪問者にメンテナンス画面が表示される。
<?php
$upgrading = time();
?>FTP やサーバーのファイルマネージャーでアクセスできない場合は、サーバー管理パネルから Web サーバー(Apache や Nginx)自体を停止するか、.htaccess に IP 制限をかけて特定の IP 以外をすべて拒否する方法も有効だ。
プラグインとテーマを強制的に無効化する
管理画面からプラグインを一括停止できない、あるいは管理画面自体が攻撃者にロックされている場合、FTP で /wp-content/plugins/ ディレクトリごとリネームする(例: plugins_backup)。これにより、WordPress は全プラグインを無効化した状態で起動する。同様に、/wp-content/themes/ から現在のテーマを除く全テーマを別ディレクトリに退避し、標準テーマ(Twenty Twenty-Five 等)のみを残す。
ログを保全して侵入経路を特定する
WP Activity Log のデータは攻撃者に消去される前にエクスポートする。CSV または JSON でダウンロードし、ローカルに保存する。このとき、サーバーのアクセスログ(access.log)とエラーログ(error.log)も必ず取得する。ログから得るべき情報は「攻撃元 IP」「削除が実行された正確な日時」「リクエスト URL(特に POST リクエスト)」「User-Agent」の4点だ。
「Unknown user」による削除操作が大量に記録されている場合、リクエスト URL が wp-admin/admin-ajax.php や wp-json/ を含んでいないかを重点的に確認する。これらが含まれていれば、AJAX や REST API 経由の攻撃である可能性が高い。
バックアップからの復旧とデータ整合性の確認

攻撃発生前の正常な状態がわかっているバックアップがあれば、それをリストアする。このケースのように2日前のバックアップが存在する場合、消失した会員データはその時点のものに戻るが、2日間に新規登録した会員や更新されたデータは失われるため、復旧後に差分を手動で補完する必要がある。
データベースをリストアする手順
バックアップが SQL ダンプファイル(.sql または .sql.gz)の場合、phpMyAdmin またはサーバーのコマンドラインからインポートする。WordPress のデータベース全体を置き換える場合は、まず現在の全テーブルを削除(DROP)してからインポートする。この操作は取り返しがつかないため、必ず現在のデータベースも別名でエクスポートしてから実行する。
# コマンドラインでのリストア例
mysql -u ユーザー名 -p データベース名 < backup.sqlリストア後、MemberPress の会員数が期待通りに戻っているか、会員のサブスクリプション状況や支払い履歴が正しく関連付けられているかを必ず確認する。特に、WooCommerce と連携している場合は wp_usermeta テーブルの整合性もチェックする必要がある。
再発を防ぐための恒久対策

復旧が完了したら、同じ攻撃を二度と受けないようにするための対策を即座に実施する。サーバー侵入を許した原因が残ったままだと、再度同じ経路から攻撃される危険が極めて高い。
全ファイルの改ざんチェックとマルウェアスキャン
WordPress のコアファイル、プラグイン、テーマのすべてについて、オリジナルの配布ファイルと比較して改ざんされていないかを確認する。WordPress の管理画面から「サイトヘルス」→「情報」→「ファイルの整合性」でコアファイルのチェックが可能だが、プラグインとテーマは手動かセキュリティプラグイン(Wordfence や Sucuri 等)を使ってスキャンする。特に、wp-content/uploads/ 内に .php ファイルが存在していないかを重点的に調べる。
管理者アカウントの総点検とパスワード再設定
すべての管理者アカウントについて、覚えのないユーザーが追加されていないか、権限が勝手に昇格されていないかを確認する。wp_users テーブルと wp_usermeta を直接確認し、不審な管理者を削除する。その上で、全管理者と編集者のパスワードを強制的にリセットし、可能であれば二要素認証(2FA)を導入する。WordPress 6.8 以降は標準でパスキー認証が利用できるため、セキュリティキーを使ったログインも有効な選択肢だ。
データベースのアクセス制限と監査の強化
データベースへの外部からの直接アクセスを遮断するため、phpMyAdmin などの管理ツールを公開ディレクトリに置かない、または IP 制限と HTTP 認証をかける。また、wp-config.php に以下の定数を追加して、WordPress のファイル編集機能を無効化しておくことで、管理画面を乗っ取られた場合でもテーマやプラグインのコードが書き換えられることを防げる。
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true); // 必要な場合のみXML-RPC と REST API のアクセス制限
XML-RPC を使用していない場合は .htaccess でブロックするか、プラグインで完全に無効化する。REST API は多くのプラグインが依存しているため完全には無効化できないが、認証が必要なエンドポイントに対して適切な権限チェックが実装されているかを確認する。特に、MemberPress やカスタムプラグインが提供する REST API エンドポイントは、開発元のドキュメントでセキュリティ設定を再確認する。
よくある質問
WP Activity Log に「Unknown user」と表示されるのは必ずハッキングか
必ずしもそうとは限らないが、高い確率で不正アクセスが疑われる。プラグインのバグやデータベースの不整合でも発生しうるが、同時に大量のデータが削除されている場合は攻撃の可能性を第一に考えるべきだ。特に、管理者権限を持たない IP からの操作が記録されている場合はほぼ確実に侵入されている。
プラグインの更新が突然大量に表示されたのはなぜか
共通ライブラリやフレームワークに重大な脆弱性が見つかり、複数のプラグインが一斉にセキュリティアップデートをリリースした可能性が高い。WordPress 本体の緊急アップデートが同日にリリースされていることも、何らかの広範囲に影響する脆弱性が公表されたことを示唆している。これらの更新は速やかに適用すべきだ。
バックアップから復旧した後、消えたデータは完全に戻るのか
バックアップ取得時点のデータは戻るが、それ以降に追加・変更されたデータは復元されない。MemberPress の会員情報の場合、新規登録者やサブスクリプションの変更履歴が失われるため、復旧後に会員からの問い合わせをもとに手動で補完する必要がある。決済情報は決済代行サービス側に残っていることが多いため、そちらを参照して復元できる場合もある。
WP 7.0.1 への更新はすぐに適用すべきか
重大なセキュリティ修正を含むマイナーアップデートの場合、速やかな適用が推奨される。ただし、大量削除が発生した環境では、まずバックアップからの復旧と侵入経路の遮断を完了させてから更新を行う。更新前に全ファイルの改ざんチェックを済ませ、マルウェアが残っていない状態で適用するのが安全だ。
この記事のポイント
- 「Unknown user」による大量削除はデータベース直接操作か管理者乗っ取りが原因の可能性が高い
- 発見後は即座にメンテナンスモードでサイトを遮断し、プラグインを強制無効化して攻撃を止める
- WP Activity Log とサーバーログを直ちにエクスポートし、攻撃元 IP と侵入経路を特定する
- バックアップからデータベースをリストアし、復旧後に全ファイルの改ざんチェックとマルウェアスキャンを実施する
- XML-RPC の無効化、REST API の権限確認、二要素認証の導入で再発を防ぐ

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

Shield SecurityのcookieがNginxキャッシュを止める時の解決策
Shield Security の icwp-wpsf-notbot cookie がサーバーのページキャッシュを妨害する問題は、Shield の設定で「silentCAPTCHA」の複雑度を「なし」にし、かつカスタムフィルターで匿名ユーザーへの cookie 送信を停止することで解決できる。
なぜ Shield Security が全ページでキャッシュを止めてしまうのか

Shield Security はボット判定や silentCAPTCHA の動作のために icwp-wpsf-notbot という cookie をフロントエンドの全ページで発行する仕様になっている。Nginx のキャッシュ機構は原則として Set-Cookie ヘッダを含むレスポンスをキャッシュしないため、この cookie がすべてのページキャッシュを無効化してしまう。結果として x-proxy-cache: MISS が返り続け、サーバーへのリクエストが毎回発生し、レスポンスタイムが 1000ms を超える状況に陥る。
サーバー側で特定の cookie だけをキャッシュ対象から除外する設定ができない場合、プラグイン側でこの cookie を止めるのが唯一の現実的な解決策になる。
管理画面で silentCAPTCHA の複雑度を「なし」にする

Shield Security の silentCAPTCHA は、ボット防御のためにフロントエンドのページにも cookie をセットする。設定を最小限に絞り込むには、まず管理画面から操作する。
これだけでは cookie の出力が止まらないケースが多い。Shield は silentCAPTCHA の設定に関わらず、フロントエンドの訪問者に対して一律に icwp-wpsf-notbot をセットする内部ロジックを持っているためだ。ここから先はコードレベルの対応が必要になる。
フィルターフックで匿名ユーザーへの cookie 送信を無効化する

Shield Security は icwp-wpsf-notbot cookie を制御するための専用フィルターを提供している。テーマの functions.php に数行のコードを追加すれば、ログインしていない一般訪問者に対する cookie の送信だけを停止できる。
functions.php に追加するコード
以下のコードを子テーマの functions.php に追加する。子テーマを使用していない場合は、Code Snippets プラグインなどで追加してもよい。テーマの直接編集はアップデートで消えるため避ける。
/**
* Shield Security の icwp-wpsf-notbot cookie をログインしていないユーザーには送信しない
*/
add_filter( 'icwp_shield_set_notbot_cookie', function( $set_cookie ) {
if ( ! is_user_logged_in() ) {
return false;
}
return $set_cookie;
} );このフィルターは icwp-wpsf-notbot cookie をセットする直前に呼び出される。ログインしていないユーザーの場合は false を返して cookie の発行をブロックし、ログイン済みユーザーには通常通り cookie を許可する。管理画面のログイン保護や IP ブロック、ファイアウォールなどのコア機能には影響しない。
動作確認の手順
- シークレットウィンドウでサイトにアクセスする
- ブラウザの開発者ツール(F12)→「アプリケーション」タブ→「Cookie」で
icwp-wpsf-notbotが存在しないことを確認する - レスポンスヘッダーから
Set-Cookieが消えていることを確認する - 2回目以降のアクセスで
x-proxy-cache: HITが返ることを確認する
全プラグインを最新に保って不要な干渉を防ぐ

Shield Security はアップデートの頻度が高く、バージョンによって内部のフィルター名が変更されることがある。Shield 22.1.3 および WordPress 7.0.1、PHP 8.2 環境では上記のフィルターが有効だが、プラグインが更新された際にはフィルター名が維持されているかを確認する必要がある。
また、キャッシュ系プラグインや CDN を併用している場合は、cookie 停止後にキャッシュを完全にクリアしてからテストすること。古いキャッシュが残っていると HIT になっていてもレスポンスが遅いままに見える場合がある。
よくある質問
SilentCAPTCHA を無効にしただけでは cookie は消えないのか
多くの場合、管理画面の設定だけでは cookie の出力は止まらない。Shield は silentCAPTCHA が無効でもフロントエンドの全リクエストに cookie をセットする内部挙動を持っている。確実に止めるにはフィルターフックの追加が必要だ。
このフィルターでログイン保護やファイアウォールは機能しなくなるか
今回のコードは匿名ユーザーへの icwp-wpsf-notbot cookie 送信だけを止めるもので、IP ブロックやブルートフォース保護、ファイアウォールといった Shield の主要防御機能はすべて通常通り動作する。ログインしたユーザーには引き続き cookie がセットされる。
functions.php を直接編集するのはリスクがないか
テーマの functions.php を直接編集すると、テーマのアップデートで変更が失われる。必ず子テーマを作成するか、Code Snippets のようなコード管理プラグインを使用する。また、コード追加前にサイトのバックアップを取得しておくと安全だ。
フィルターが効かない場合の確認ポイントは
Shield のバージョンが古い、あるいは逆に新しすぎてフィルター名が変更されている可能性がある。Shield の公式ドキュメントや変更履歴を確認する。また、キャッシュ系プラグインでサーバー側のキャッシュとは別にページキャッシュが残っていると、cookie 停止後も古いレスポンスが返り続けるため、すべてのキャッシュをクリアしてからテストする。
レンタルサーバーのキャッシュ設定で cookie ごとの除外はできないのか
共用サーバーの Nginx キャッシュ設定はサーバー全体で一律に適用されることが多く、特定の cookie だけを除外する柔軟な設定は提供されないケースがほとんどだ。サーバー側で対応できない以上、プラグイン側で cookie を止めるのが最も確実な方法になる。
この記事のポイント
- Shield Security の icwp-wpsf-notbot cookie が Nginx のページキャッシュを全面的に阻害する
- 管理画面で silentCAPTCHA の複雑度を「なし」にしても cookie は止まらない
- functions.php にカスタムフィルターを追加しログインしていないユーザーへの cookie 送信を停止する
- フィルター追加後はシークレットウィンドウで Set-Cookie ヘッダーと x-proxy-cache の値を確認する
- プラグインのアップデート後はフィルター名の変更に注意しキャッシュを完全クリアして再テストする

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

Elementorテキストエディタで段落が勝手に横並びになる時の直し方
Elementorのテキストエディタウィジェットで複数段落を入力したとき、編集画面では問題ないのに公開ページで急に横並びになる現象は、WoodMartテーマが組み込むフレックスボックス(Flexbox)のグローバルスタイルや、テーマ側の段組み(カラム)レイアウト用CSSが誤って適用されていることが主な原因だ。
なぜElementorの段落が公開サイトで横並びになるのか

WoodMartテーマは、WPBakeryと並んでElementor対応を謳う多機能テーマだ。その内部ではグリッドレイアウトや商品カードの並びを柔軟に制御するため、.entry-content や .elementor-widget-text-editor といったコンテナに対して display: flex や flex-wrap: wrap をデフォルトCSSとして指定しているケースがある。
このような設定が有効だと、コンテナ直下の <p> タグはフレックスアイテムとして扱われ、利用可能な幅の中で自動的に横方向へ配置されるのだ。通常のブロック要素であれば改行されるため縦に積み重なるが、フレックスコンテナの子要素はこの規則から外れる。その結果、編集画面では普通に見えていても、テーマのグローバルCSSがロードされるフロントエンドでのみ崩れが発生するという、なかなか気づきにくいトラブルになる。
ほかにも、Elementorの「段組み」設定の競合や、意図せず有効化されたCSSの最適化機能が影響することもあるが、ほとんどはWoodMartのベーススタイルが起点だ。次の項で切り分け手順を確かめつつ修正していく。
問題の再現状況をデモで確認する

「会社概要についての本文がここにあります。WoodMartの特徴を活かしたレイアウトです。」
「サービス一覧のご案内です。Elementorを使って自由に編集した内容がここに入ります。」
「会社概要についての本文がここにあります。WoodMartの特徴を活かしたレイアウトです。」
「サービス一覧のご案内です。Elementorを使って自由に編集した内容がここに入ります。」
フレックスコンテナの子要素だから横に並ぶ、という仕組みをこのデモで示している。原因のCSSを特定し、段落の並びをブロック表示に戻せば解決できる。
ElementorとWoodMartで段落が横並びになるCSSの特定と修正手順

ここからは実際にサイトを修正するための手順を説明する。作業は大きく3ステップだ。修正用のCSSは数行で済むが、きちんと原因を突き止める手順を踏まないと、後日ほかのレイアウト崩れを引き起こす可能性がある。
ブラウザの検証ツールで適用されているスタイルを調べる
まずはChromeのデベロッパーツール(F12キー)を使って、公開ページ上のテキストエディタ部分を調べる。<p> タグを右クリックし「検証」を選択すると、スタイルパネルで各要素に適用されているCSSを確認できる。
ここで最も注目すべきは、テキストエディタのラッパー要素(たいていは .elementor-widget-text-editor か、WoodMartが生成する固有のクラスが付いたdiv)に対して display: flex や display: grid が指定されていないかどうかだ。仮に以下のようなCSSが表示された場合、これが横並びの直接的な原因になる。
.elementor-widget-text-editor {
display: flex;
flex-wrap: wrap;
gap: 20px;
}このCSSがWoodMartの親テーマ、または子テーマのスタイルシートから読み込まれている場合は、検証ツールの右上にファイル名と行番号が表示される。原因となるファイルが特定できたら、次の手順で上書きするCSSを追加しよう。
修正用CSSを追加する場所を選ぶ
原因となっている display: flex を打ち消すには、以下のようなCSSを適用すればよい。要素をブロック表示に戻すには display: block を指定し、内部の段落が確実に積み重なるようにする。
.elementor-widget-text-editor {
display: block !important;
}
.elementor-widget-text-editor p {
display: block;
width: 100%;
}このCSSは以下のいずれかの場所に追加する。優先順位順に記す。
- 管理画面の「外観」→「カスタマイズ」→「追加CSS」(最も手軽で、テーマに関係なく安全)
- WoodMartのテーマオプションにあるカスタムCSS欄
- Elementorのサイト設定内のカスタムCSS
注意点として、追加CSSに !important を使うのはどうしても優先度で負ける場合の最終手段だ。まずは !important なしで試し、効かなければ付与するという手順を踏むほうが、意図しないカスケード崩れを防げる。上記のコード例では !important を付記したが、自身の環境で不要なら省略して構わない。
Elementorとキャッシュのクリアを忘れずに行う
CSSを追加してもすぐに反映されない場合、Elementor固有のキャッシュや、サーバー側のキャッシュが影響している。Elementorの「ツール」メニューから「CSSとデータを再生成」を実行し、さらに「Elementor」→「設定」→「高度な設定」でCSSの出力方法を「外部ファイル」から「内部埋め込み」に切り替えて一時的に様子を見るのもひとつの手だ。
サーバーでLiteSpeed CacheやW3 Total Cacheなどのキャッシュ系プラグインを使っているなら、管理画面から全キャッシュを削除しておく。とくに「CSSの最適化」や「CSSの結合」をオンにしている場合、追加したCSSが適用されない原因になりやすい。キャッシュをクリアしたあとに、シークレットモードで公開ページを開いて検証する。
テーマをアップデートする際の注意点と恒久対策

今回の現象はあくまでテーマの全体的なスタイル指定が原因であり、Elementorのバグではない。WoodMartが将来のアップデートでこのフレックスボックス指定を変更する可能性もゼロではないが、テーマのアップデートに依存するのはリスクが高い。
恒久的な対策としては、親テーマを直接編集せず、子テーマの style.css か「追加CSS」に上書きルールを残すことだ。もしテーマのバージョンアップ後に問題が再発したら、原因のCSSセレクタが変わっていないか検証ツールで再確認し、セレクタを合わせて更新すればすぐに直せる。
複数ページで同じテキストエディタウィジェットを使っている場合は、サイト全体に影響する「追加CSS」での対応が推奨だ。特定のページや投稿タイプでのみ発生しているなら、該当ページのElementor編集画面で「サイト設定」→「カスタムCSS」を使い、スコープを絞った指定をする手もある。
よくある質問
テキストエディタ以外のウィジェットでも同じ症状は出るのか
見出しウィジェットや画像ウィジェットなど、直下に複数のブロック要素がぶら下がらない種類のウィジェットでは、この現象はまず起きない。ただし「内部セクション」や「Flexboxコンテナ」などの新しめのコンテナ系ウィジェットを使っていると、似た横並びが発生することがある。
WoodMart以外のテーマでも同じことが起きるのか
汎用的なテーマでは稀だが、カラム多用型の多機能テーマ(Avada、The7、Flatsomeなど)でも同様の報告がある。いずれの場合も、根本原因はテーマが付与しているフレックスボックスやグリッドのグローバルCSSだ。
追加CSSで直したのにスマホ表示だけ直らない
デスクトップでは修正されても、モバイル用のメディアクエリ内で再度 flex-direction: row が指定されている可能性がある。検証ツールでデバイスモードに切り替え、同じテキストエディタで適用されているスタイルを再確認する。必要ならメディアクエリを追加して上書きしよう。
子テーマのstyle.cssに書いても効かないのはなぜか
読み込み順の問題がほとんどだ。親テーマのCSSが子テーマより後で読み込まれていると、詳細度が同じなら後勝ちで上書きされる。functions.phpで子テーマのCSSを依存関係付きで読み込んでいるか確認し、どうしても効かないなら「追加CSS」機能(wp_headの最後で出力される)を使うほうが確実だ。
この記事のポイント
- Elementor編集画面では正常でもフロントエンドでテキスト段落が横並びになる場合、WoodMartが付与するflex指定が原因
- ブラウザの検証ツールで適用されているdisplayプロパティを特定し、追加CSSでブロック表示に戻す
- 修正CSSは外観カスタマイズの「追加CSS」がもっとも安全で確実
- CSS追加後はElementorのCSS再生成とサーバーキャッシュのクリアをセットで行う
- テーマアップデート後も再発しにくいよう、恒久対策として上書きルールを残しておく

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化
・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門
・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標
・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意
・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている
