Category Archive お悩み・トラブル解決

Booking Calendar更新後にサイトが壊れた時の原因と直し方

Booking Calendar更新後にサイトが壊れた時の原因と直し方

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

なぜバージョン 11.4.2 への更新でサイトが壊れたのか

なぜバージョン 11.4.2 への更新でサイトが壊れたのか

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

とくに 11.4.2 では内部 API の変更が加えられており、Pro 版が旧バージョンのまま無料版だけを更新すると競合が起きやすい。この状態で WordPress の「このサイトで重大なエラーが発生しました」というメッセージが表示されたり、管理画面にアクセスできなくなったりする。

サイトを元に戻す具体的な手順

サイトを元に戻す具体的な手順

以下の手順で、無料版と Pro 版を安全に最新へ揃える。作業前に必ずサイト全体のバックアップを取得しておく。

STEP 1 FTP またはホスティングのファイルマネージャで /wp-content/plugins/ にアクセスする
STEP 2 無料版と Pro 版の両方のフォルダを一時的にリネームして無効化する(例: bookingbooking_old
STEP 3 無料版を WordPress.org から最新版(11.4.2)で再インストールし有効化する
STEP 4 開発元サイトから Pro 版の最新をダウンロードし、管理画面からアップロードして有効化、ライセンスキーを再入力する

プラグインフォルダを特定して無効化する

サイトが壊れて管理画面に入れない場合は、FTP(File Transfer Protocol)クライアントやレンタルサーバーのファイルマネージャを使う。/wp-content/plugins/ ディレクトリ内に、無料版(通常は booking または booking-calendar)と Pro 版(booking-calendar-prowpdev-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 版のリリース確認後に揃えて更新する
WordPressをサブフォルダにインストールするとREST APIが404になる原因と直し方

WordPressをサブフォルダにインストールするとREST APIが404になる原因と直し方

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

なぜサブフォルダ環境でプラグインのAPIが404になるのか

なぜサブフォルダ環境でプラグインの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()が返す値を検証し、他のプラグインとの競合を調べる。

STEP 1 問題のプラグインを最新版に更新する
STEP 2 パーマリンク設定をリセットして API ルートを再構築する
STEP 3 rest_url() の戻り値を検証し、サブフォルダが含まれるか確認する
STEP 4 全プラグインを無効化して競合を切り分ける

プラグインを最新版に更新する

本件ではバージョン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.phpWP_HOMEWP_SITEURLが正しくサブフォルダを含んだ値で定義されているか確認する。

全プラグインを無効化して競合を切り分ける

それでも404が解消しない場合、別のプラグインがREST APIのルーティングに干渉している可能性がある。すべてのプラグインを一括で無効化し、問題のエンドポイントにアクセスして200番台のレスポンスが返るかテストする。正常動作が確認できたら、プラグインを1つずつ有効化して原因のプラグインを特定する。キャッシュ系プラグインやセキュリティプラグインは、REST APIへのリクエストをブロックしたり、URLを書き換えたりする設定項目を持つことがあるため、該当するプラグインの設定もあわせて確認する。

よくある質問

サブフォルダにインストールする際にwp-config.phpで注意すべき点は?

WP_HOMEWP_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認識が正しいか検証する
  • 全プラグインの無効化で競合を切り分け、キャッシュやセキュリティ系プラグインの干渉を疑う
Gravity Forms PDFで合計金額が倍になる原因と修正方法

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() を複数回呼ぶと値が積み上がるのか

なぜ 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倍になる。通常、こうした合計取得メソッドは毎回ゼロから計算し直すべきであり、内部で継ぎ足す構造は意図したものでない可能性が高い。

Before(問題のある状態)
1回目呼び出し: 小計=10,000 + 送料=500 → total=10,500
変数 self::$total が 10,500 を保持したまま
2回目呼び出し: 10,500 + 10,000 + 500 → total=21,000
After(修正後のあるべき動作)
1回目呼び出し: 小計=10,000 + 送料=500 → total=10,500
2回目呼び出し: 変数をリセット後 再計算 → total=10,500
静的変数が保持され加算される問題  毎回リセットして再計算する修正後

上の図のように、2回目で合計が倍になる。特に「小計」「消費税」「総合計」など複数の金額を PDF テンプレートに配置する場合にこの問題が顕在化しやすい。

get_total() 修正の基本的な考え方

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を表示」ボタンで実際の請求書を開き、同じ合計が要求された位置すべてに正しく表示されているかをチェックする。サイトでキャッシュプラグインを使っている場合は、キャッシュを全削除してから確認すると確実だ。

STEP 1 子テーマの functions.php にカスタムクラスを定義する
STEP 2 PDF テンプレート内の呼び出しを Custom_GFPI_Helpers に変更する
STEP 3 キャッシュを削除し、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() も併せて修正を検討する
WooCommerceで北アイルランド向けVAT税率だけ20%に設定する方法

WooCommerceで北アイルランド向けVAT税率だけ20%に設定する方法

{ “title”: “WooCommerceで北アイルランド向けVAT税率だけ20%に設定する方法”, “meta_description”: “WooCommerceで英国は税率0%、北アイルランドだけ税率20%に設定するには、国「UK」と州コード「Northern Ireland」を組み合わせる。設定手順とテスト方法まで解説。”, “tags”: [“WooCommerce”, “税率設定”, “VAT”, “北アイルランド”, “EC運営”, “Brexit”], “slug”: “woocommerce-northern-ireland-tax-rate”, “image_prompt”: “WooCommerceのロゴ(紫の丸みを帯びたマーク)を3Dで目立つように大きく配置する。上部には、ダークなEU地図の上に北アイルランドだけがハイライトされ、20%のプレートが浮かぶリアルな構図。下部には英国本土と北アイルランドが色分けされたVAT設定画面のUIを配置。構図は上下分割スタイルとし、主要な視覚要素を画面の上部と下部に配置して、その間を自然で大気感のあるトランジションでつなぐ。画面を横切る水平の帯やストライプは描かない。画像の右下の領域には文字・ロゴ・重要な被写体を置かず、背景や余白にする。アスペクト比16:9。UI画面・ダッシュボード・コードエディタ・管理画面が写る場合、その中の文字はすべて英語にする。ノートPCやモニターが写る場合は極細ベゼルの現代的なデザインにする。カレンダー・画面・書類・タイムラインに年号の数字を表示しない。”, “featured_text”: “北アイルランドだけ\n税率20%にしたい?” }

WooCommerceで英国本土と北アイルランドに異なるVAT税率を設定するには、税率設定画面で国として「United Kingdom (UK)」を選び、州コードに「Northern Ireland」を指定して、英国全体の税率と北アイルランドのみの税率をそれぞれ登録する。

WooCommerceの税率設定で英国と北アイルランドを区別できない原因

WooCommerceの税率設定で英国と北アイルランドを区別できない原因

WooCommerceは国単位で税率をマッチさせるが、標準状態では英国全体が「GB」という国コードでまとめられている。そのため、英国本土向けの税率と北アイルランド向けの税率を単一の国設定で区別できないように見える。しかし実際には、州コード(State Code)を使って地域を細分化できる仕組みが備わっている。英国本土と北アイルランドはVAT制度上、EUと英国内で異なる扱いを受けるため、州レベルでの切り分けが不可欠だ。

WooCommerceで英国本土と北アイルランドの税率を別々に設定する手順

WooCommerceで英国本土と北アイルランドの税率を別々に設定する手順

WooCommerceの管理画面から、税率の新規追加・編集を行う。まずは英国全体に対する税率0%を設定し、その後に北アイルランドだけを対象とした税率20%を追加する。この順序で設定する必要は必ずしもないが、後のテストが楽になる。

税率 1 対象: 英国(本土)
国コード: GB(州コード未指定)
税率: 0%(VAT非課税)
税率 2 対象: 北アイルランドのみ
国コード: GB 州コード: Northern Ireland
税率: 20%(標準VAT)

このデモは英国全体(州コードなし)と北アイルランド(州コードあり)の2つの税率エントリを示している。実際の設定画面でも同じ構造で登録する。

英国全体の税率0%を設定する

英国全体の税率0%を設定する

WooCommerceの管理メニューから「WooCommerce」→「設定」→「税率」タブを開く。「税率を追加」ボタンを押し、以下のように入力する。

  • 国コード: ドロップダウンから「United Kingdom (UK)」を選ぶ
  • 州コード: 何も入力せず空欄のままにする
  • 税率: 0%(英国本土向けVATは0%のため)
  • 税率名: 例「UK VAT 0%」など分かりやすい名前
  • 税率の優先度: 0(デフォルトで問題ない)

「変更を保存」をクリックする。これで英国本土向けの注文には0%が適用される。

北アイルランド向けの税率20%を設定する

同じ税率一覧画面で再び「税率を追加」を押す。今度は州コードを指定して北アイルランドだけに20%が適用されるエントリを作る。

  • 国コード: 「United Kingdom (UK)」を選ぶ
  • 州コード: ドロップダウンまたは手入力で「Northern Ireland」を指定する。入力欄に文字を打つと候補が表示される
  • 税率: 20%(標準VAT)
  • 税率名: 例「Northern Ireland VAT 20%」
  • 税率の優先度: 0

「変更を保存」をクリックする。WooCommerceは注文時に配送先住所の国と州を照合し、より具体的な州コード指定のある税率エントリを優先して適用する。これで北アイルランド宛ての注文には20%が、それ以外の英国本土宛てには0%が自動で適用される。

設定後は必ずテスト購入で税率を確認する

本番運用する前に、かならずテストモードまたはステージング環境で実際の購入フローを試してほしい。配送先住所を英国本土(例: London)と北アイルランド(例: Belfast)の2パターンで入力し、カートやチェックアウト画面に表示される税額が想定どおりになっているか確認する。

もし北アイルランド住所でも税率が0%のままだった場合は、税率エントリの州コードが正しく「Northern Ireland」になっているか、また住所欄に入力した州名が税率設定のものと一致しているかをチェックする。WooCommerceは住所の州名と税率テーブルの州コードを厳密に突き合わせるため、スペルミスや表記ゆれがあるとマッチしない。

よくある質問

英国全体の税率エントリと北アイルランドの税率エントリの優先度は同じでよいのか

問題ない。どちらも優先度が同じ場合、WooCommerceはより具体的な条件を持つエントリ(州コード指定あり)を自動的に優先する。本土用(州指定なし)より北アイルランド用(州指定あり)のほうが具体的なため、優先度の値にかかわらず正しく適用される。

州コードに「Northern Ireland」が表示されない場合はどうするか

WooCommerceの州コードリストはデフォルトで主要な州を含んでいるが、何らかの理由で表示されない場合は手入力も可能だ。入力欄に直接「Northern Ireland」とタイプして保存すれば機能する。もしどうしてもリストに出ないなら、WooCommerceの一般設定で販売地域を「すべての国に出荷する」などに一時変更してから再確認する。

欧州連合(EU)のVAT設定と衝突しないか

WooCommerceの税率設定は国単位・州単位で独立しているため、EU加盟国向けの税率エントリとは別に管理できる。英国(GB)向けのエントリは、EUの税率設定テーブルとは独立して動作するので衝突しない。ただしEU全域向けの税率設定をまとめて有効にしている場合は、英国向けエントリが優先されるよう、税率の優先度や対象地域を整理しておくと安心だ。

北アイルランド宛ての配送時にだけ異なる税率を表示したいが可能か

可能だ。本記事で解説した州コード指定の方法を使えば、北アイルランド向けの注文だけ異なる税率(例: 20%)を表示し、英国本土向けには別の税率(例: 0%)を表示できる。条件は住所の州名が税率エントリの州コードと一致することだけだ。

WooCommerce以外のプラグインでもこの方法は使えるか

この解説はWooCommerceの税率設定機能を前提としている。ECプラグインによっては州コードを使った税率の細分化に対応していない場合もあるため、利用しているプラグインのドキュメントを確認する必要がある。WooCommerceを推奨する趣旨ではないが、同様の要件を満たすには国と州を組み合わせた柔軟な税率設定ができるプラグインを選ぶことがポイントになる。

この記事のポイント

  • WooCommerceでは国コード「GB」と州コード「Northern Ireland」で税率を分けられる
  • 州コード指定のある税率エントリは、指定のないエントリより優先される
  • 英国全体に税率0%、北アイルランドに税率20%をそれぞれ追加する
  • 設定後はテスト購入で英国本土と北アイルランド両方の税額を確認する
  • 州コードは手入力でも有効、表示されない場合は直接タイプする
WordPress 7.0.1でクラシックエディタ保存できない時の原因と直し方

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 でクラシックエディタが動作しなくなるのか

根本原因は 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.3 にダウングレードすることだ。PHP 8.4 はリリースされたばかりで、WordPress エコシステム全体の完全な互換性が確保されるまでは安定動作が見込める 8.3 を使うほうが無難である。

PHP 8.4
クラシックエディタ保存不可 → 一覧にリダイレクト → 記事消失
STEP 1 サーバー管理画面から PHP 設定を開く
STEP 2 PHP 8.3 を選択して適用する
PHP 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 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 は公式推奨でありセキュリティ面でも安全に運用できる
カートが0円だとWooCommerceの注文が完了しない時の直し方

カートが0円だとWooCommerceの注文が完了しない時の直し方

なぜカート合計が0円だとチェックアウトが完了しないのか

なぜカート合計が0円だとチェックアウトが完了しないのか

WooCommerce の最低購入金額制御プラグイン(たとえば Minimum Purchase Amount Control など)は、指定した金額未満の注文を受け付けないように設計されている。このプラグインは通常、カートの合計金額が設定した最低金額を下回るとチェックアウトをブロックする。しかし「無料商品を許可する」「クーポンで0円になる場合を許可する」といった例外ルールを設定していても、内部的にはチェックアウト処理の最終段階で金額を再評価し、ブロックをかけてしまうケースがある。

このとき画面上では「注文する」ボタンを押せてしまい、一見すると購入が完了したように見える。ところが実際には注文データが正しく確定されず、商品がカートに取り残される。リダイレクト先の注文確認ページ(サンキューページ)にも遷移しない。プラグインを停止すると問題が消えることから、プラグインのゼロ円ブロック機能が直接の原因だ。

フィルターフックでゼロ円チェックアウトを許可する手順

フィルターフックでゼロ円チェックアウトを許可する手順

このプラグインには、ゼロ円の注文を許可するための専用フィルターフック ct_mpac_allow_zero_total が用意されている。このフックを有効にすれば、無料商品やクーポンで合計が0円になったカートでも問題なくチェックアウトが完了するようになる。

以下の手順では、子テーマの functions.php に数行のコードを追加する。子テーマを使っていない場合は、Code Snippets プラグインなどを利用しても同じ結果が得られる。

STEP 1 子テーマの functions.php を開く(外観 → テーマファイルエディター)
STEP 2 ファイル末尾に以下のコードを追加する
STEP 3 ファイルを更新して保存する
STEP 4 0円になる商品をカートに入れてチェックアウトをテストする

追加するコードは次のとおりだ。

add_filter( 'ct_mpac_allow_zero_total', '__return_true' );

この1行で、プラグインがゼロ円の注文を許可するようになる。__return_true は WordPress の組み込み関数で、単純に true を返す。フィルターにこれを渡すことで「常に許可する」という挙動に切り替わる仕組みだ。

Code Snippets プラグインを使う場合は、新規スニペットを追加し、上記のコードを貼り付けて「サイト全体で実行」に設定すればよい。

コード追加後も改善しない場合の確認ポイント

コード追加後も改善しない場合の確認ポイント

フィルター名がプラグインのバージョンと合っているか確認する

プラグインのバージョンアップによってフィルター名が変更されている可能性がある。プラグインの公式ドキュメントやソースコード内で apply_filters を検索し、最新のフック名を確認するのが確実だ。特にプラグイン名が似ている別の最低購入金額プラグインに乗り換えた場合は、フック名がまったく異なるため注意が必要になる。

キャッシュ系プラグインやサーバーキャッシュの影響を疑う

functions.php を更新したのに改善しない場合、WordPress のキャッシュプラグインやサーバーレベルのキャッシュ(OPcache など)が原因で変更が反映されていないことがある。キャッシュをすべてクリアし、さらにブラウザのシークレットモードで動作をテストしてみる。OPcache が効いているレンタルサーバーでは、ファイル更新から数分間は古いコードが動き続けるケースもある。

決済ゲートウェイ側のゼロ円制限を調べる

ごくまれに、WooCommerce の決済ゲートウェイ自体が0円のトランザクションを許可していない場合がある。プラグインの問題が解消されたあともチェックアウトが進まないときは、Stripe や PayPal などのゲートウェイ設定で「0円の注文を許可する」オプションが存在しないか確認する。テスト用に代金引換や銀行振込など、実決済を伴わないゲートウェイに切り替えて試すのも有効な切り分け方法だ。

よくある質問

このフィルターはどのプラグインに対応しているのか

ct_mpac_allow_zero_total は、主に「Minimum Purchase Amount Control for WooCommerce」系のプラグインで使われるフックだ。プラグインの作者が異なるとフック名も変わるため、必ず利用中のプラグインのドキュメントを参照してほしい。

フィルターを追加する以外の解決策はあるか

プラグインの設定画面で「無料商品を許可」「クーポン適用後の0円を許可」といったチェックボックスが用意されていれば、そちらを有効にするだけで直ることもある。設定が存在しない場合や、設定を入れても効かないときにフィルターを使うのが確実な方法だ。

ゼロ円の注文を許可するとセキュリティ上のリスクはあるか

意図した無料商品や割引クーポン以外で0円になるカートが発生しないよう、クーポンの利用条件や商品価格の設定を適切に管理していれば大きなリスクにはならない。ただし、テストや不正利用対策として、定期的に0円注文のログを確認する運用は推奨する。

子テーマを使わずにコードを追加する方法はあるか

Code Snippets プラグインや WPCode プラグインを利用すれば、テーマファイルを直接編集せずにフィルターフックを安全に追加できる。テーマのアップデートでコードが消える心配もなく、管理画面からオンオフを切り替えられるため、まずはこちらを試すのが安心だ。

この記事のポイント

  • WooCommerce の最低購入金額プラグインが0円の注文をブロックし、チェックアウトが完了しない
  • フィルターフック ct_mpac_allow_zero_totalfunctions.php に追加すればゼロ円注文を許可できる
  • Code Snippets プラグインを使えば子テーマの編集なしで安全にコードを追加可能
  • 改善しない場合はキャッシュのクリアや決済ゲートウェイの0円制限も確認する
データベース接続確立エラーの原因と復旧手順

データベース接続確立エラーの原因と復旧手順

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

なぜ「データベース接続確立エラー」が突然発生するのか

なぜ「データベース接続確立エラー」が突然発生するのか

このエラーは WordPress がデータベースに接続できないときに表示される。日本語環境では「データベース接続確立エラー」というメッセージが画面に表示され、サイト全体が表示できなくなる。原因は大きく4つに分けられる。

  • wp-config.php 内のデータベース名・ユーザー名・パスワード・ホスト名のいずれかが誤っている
  • データベースサーバー自体がダウンしている(サーバー障害・メンテナンス)
  • データベースサーバーは稼働しているが、負荷集中で応答不能になっている
  • データベースが破損している(テーブルクラッシュなど)

サイトを長期間触っていなかったのに突然エラーが出た場合は、サーバー側で MySQL や MariaDB のバージョンアップ、パスワード変更、セキュリティ設定の変更が行われた可能性が高い。WordPress 側の設定ファイルは変わらないまま、サーバー側の接続条件だけが変わることで不一致が起きる。

Before(エラー発生中)
ブラウザに「データベース接続確立エラー」が表示される
wp-config.php とデータベースの認証情報が不一致、または DB サーバーが停止
After(復旧後)
サイトが正常表示される
正しい接続情報で WordPress がデータベースにアクセスできる状態
エラー状態  復旧後

エラーが出たらまず試す3つの切り分け

エラーが出たらまず試す3つの切り分け
STEP 1 サーバー会社にデータベースサーバーの稼働状況を確認する
STEP 2 wp-config.php の接続情報をサーバー管理画面の値と照合する
STEP 3 phpMyAdmin などでデータベースに直接接続できるか試す

サーバー会社にデータベースサーバーの状態を問い合わせる

最も確実で早いのが、利用しているサーバー会社のサポートに連絡することだ。データベースサーバーがダウンしていれば、自分で何をしても復旧しない。管理画面にログインできなくても、サーバー会社のコントロールパネル(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 で修復を試みる
  • 日常的にバックアップと接続情報の控えを取っておくことで復旧時間を短縮できる
WordPress会員データが大量削除された時の原因と復旧手順

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 経由で直接データベース操作を行うカスタムエンドポイントがテーマやプラグインに存在すると、認証をすり抜けて大量削除が実行される危険がある。

大量削除が発生する3つの経路
A. データベース直接操作 SQL インジェクションやサーバー侵入により、DELETE 文を直接実行。WordPress のログを一切通過しないため「Unknown」になる。
B. 管理者アカウント乗っ取り 乗っ取った管理者で管理画面から一括削除。通常はユーザー名が残るが、アカウントごと削除された可能性もある。
C. REST API や XML-RPC の悪用 認証の脆弱性を突き、API 経由で削除リクエストを送信。プラグイン独自のエンドポイントに注意が必要。
最も深刻な経路  緊急調査が必要な経路

同時に多数のプラグイン更新が表示され、WordPress 7.0.1 への更新も同日にリリースされたという状況は、実際に重大な脆弱性が公表され、各開発者が一斉にパッチを配布している可能性を示唆している。更新が突如10件以上積み上がるのは、テーマやプラグインに含まれる共通ライブラリに脆弱性が見つかった場合によく見られるパターンだ。

攻撃を受けた直後にとるべき緊急対応の手順

攻撃を受けた直後にとるべき緊急対応の手順

被害の発覚から時間が経つほど、データ消失や情報流出の範囲は広がる。以下の手順を発見後30分以内に実行することで、二次被害を最小限に抑えられる。

STEP 1 サイトをメンテナンスモードに切り替え、外部からの全アクセスを遮断する
STEP 2 全プラグインとテーマを強制無効化し、攻撃者が仕込んだマルウェアの実行を止める
STEP 3 WP Activity Log をエクスポートし、攻撃元 IP と操作内容の全記録を保全する
STEP 4 直近の正常なバックアップからデータベースを復元する

メンテナンスモードでアクセスを遮断する

まず、攻撃が継続している可能性を想定し、サイト全体をメンテナンスモードに切り替える。管理画面にアクセスできる状態であれば、.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.phpwp-json/ を含んでいないかを重点的に確認する。これらが含まれていれば、AJAX や REST API 経由の攻撃である可能性が高い。

バックアップからの復旧とデータ整合性の確認

バックアップからの復旧とデータ整合性の確認

攻撃発生前の正常な状態がわかっているバックアップがあれば、それをリストアする。このケースのように2日前のバックアップが存在する場合、消失した会員データはその時点のものに戻るが、2日間に新規登録した会員や更新されたデータは失われるため、復旧後に差分を手動で補完する必要がある。

復旧の Before / After
Before(攻撃を受けた状態)
MemberPress 会員テーブルが数千件消失し「Unknown user」の削除ログのみが残っている。プラグイン更新が20件積み上がり、WP 7.0.1 が未適用。
After(復旧完了後)
バックアップから会員データをリストア。全プラグインと WP 本体を最新に更新し、不正ファイルを除去した状態でサイトを再公開。
攻撃直後の状態  復旧後の安全な状態

データベースをリストアする手順

バックアップが 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 の権限確認、二要素認証の導入で再発を防ぐ
myCred Toolkit Pro アップデート後の致命的エラーと復旧手順

myCred Toolkit Pro アップデート後の致命的エラーと復旧手順

WordPress サイトで myCred Toolkit Pro をアップデートした直後に「Class MWP_Module not found」という致命的エラーが発生し管理画面にもアクセスできなくなった場合は、最新バージョンで修正済みの可能性が高い。修正がまだ提供されていない場合でも、クラスファイルの読み込み順序を確認し手動で修正すれば復旧できる。

MWP_Module クラスが見つからない致命的エラーはなぜ起こるのか

MWP_Module クラスが見つからない致命的エラーはなぜ起こるのか

このエラーは、myCred Toolkit Pro 内の WooCommerce Plus 改修版アドオンが読み込まれる際、ベースクラス(親クラス)である MWP_Module がまだ定義されていない状態で、子クラスが呼び出されるために発生する。具体的には class-mwp-module-coupons.phpMWP_Module を継承しようとするが、その元となる抽象クラスファイルが先に読み込まれていないのだ。

本来なら abstract/class-mwp-abstract-module.php が先にロードされるべきところ、プラグインのアップデート時にファイルの欠落が起きたり、オートローダーの設定不備で読み込み順序が狂ったりすると、このエラーが表面化する。PHP は未定義クラスへの継承を許さないため、サイト全体が致命的エラーで停止してしまう。

アップデート直後にサイトがダウンした場合の緊急復旧手順

アップデート直後にサイトがダウンした場合の緊急復旧手順

エラーによって WordPress 管理画面にも入れなくなった状態では、FTP クライアントやサーバーのファイルマネージャを使ってプラグインを強制的に無効化する必要がある。データベースを直接操作する方法もあるが、ファイル名の変更がもっとも手軽で確実だ。

STEP 1 FTP クライアントでサーバーに接続し、/wp-content/plugins/ ディレクトリへ移動する
STEP 2 mycred-toolkit-pro フォルダを右クリックし、「名前の変更」で末尾に _disabled を付ける
STEP 3 ブラウザでサイトにアクセスし、管理画面 /wp-admin/ へログインできるか確認する
STEP 4 管理画面に入れたら、プラグイン一覧で Toolkit Pro が「無効」になっていることを確認し、旧バージョンへ差し替える準備をする

上の手順でプラグインを無効化すれば、サイトは正常に表示されるようになる。続いて、動作していた旧バージョン(例として 1.0.4)を再インストールして有効化するか、修正版が配布されているかを確認する。

手動でクラスファイルの読み込み順序を確認し修正する方法

手動でクラスファイルの読み込み順序を確認し修正する方法

開発元の修正版がまだ提供されていない、あるいは修正を待てない場合は、プラグインのファイルを手動で編集してクラスの読み込み順序を修正できる。修正の要点は、class-mwp-module-coupons.php に到達する前にベースクラスを確実に読み込ませることだ。

問題のファイルと修正箇所を特定する

エラーログに出力されたパスをもとに、wp-content/plugins/mycred-toolkit-pro/includes/addons/mycred-woocommerce-plus/mycred-woocommerce-plus-revamped/modules/class-mwp-module-coupons.php を開く。7 行目付近で MWP_Module を継承しているクラス定義があるはずだ。

ベースクラスのファイルは wp-content/plugins/mycred-toolkit-pro/includes/addons/mycred-woocommerce-plus/mycred-woocommerce-plus-revamped/abstract/class-mwp-abstract-module.php に存在する。これが読み込まれていないことが原因なので、子クラスのファイルの先頭で明示的に require_once を追加する。

修正前(エラー発生)
1 <?php
2
3 // エラー: 親クラスが不明
4 class MWP_Module_Coupons extends MWP_Module {
5
修正後(正常動作)
1 <?php
2 require_once plugin_dir_path( __FILE__ ) .
3 ../abstract/class-mwp-abstract-module.php‘;
4
5 class MWP_Module_Coupons extends MWP_Module {
6
修正前(親クラス未定義のまま実行)  修正後(require_once で事前に読み込み)

上記のように require_once を追加することで、クラス定義より前にベースクラスを確実に読み込める。ただし、この修正は自作テーマの functions.php に書くような一時しのぎとは異なり、プラグインのコアファイルを直接編集するため、アップデートで上書きされる可能性がある点を理解しておく必要がある。

オートローダーの確認と修正

モダンなプラグインは PHP のオートローダー(Composer の autoload など)を使ってクラスを動的に読み込む仕組みを採用している。myCred Toolkit Pro も Composer ベースのオートロードを利用している可能性が高く、composer.json の autoload 設定や名前空間のマッピングが正しいかを確認すると根本的な解決につながる。

プラグインディレクトリで composer dump-autoload -o を実行し、クラスマップを再生成するのも有効な手だ。ただし、サーバーに Composer がインストールされている必要があるため、ローカル環境で再生成してからファイルをアップロードする方法が現実的だ。

修正版がリリースされている場合の安全なアップデート手順

修正版がリリースされている場合の安全なアップデート手順

開発元から修正版が提供された場合、本番環境にいきなり適用するのは避け、最初にステージング環境で動作確認を行うのが鉄則だ。致命的エラーはサイト全体を巻き込むため、万が一のときに備えて必ずバックアップを取る。

STEP 1 本番サイトのデータベースと全ファイルをバックアップする(プラグイン「UpdraftPlus」やサーバー側のスナップショット機能を使う)
STEP 2 ステージング環境にバックアップを復元し、Toolkit Pro を最新版へアップデートする
STEP 3 WooCommerce のポイント付与やクーポン連携が正常に動くか、テスト注文を行って検証する
STEP 4 問題なければメンテナンス時間帯を設け、本番環境でも同様にアップデートする

ステージング環境がない場合は、本番環境の深夜帯などアクセスが少ない時間にメンテナンスモードへ切り替えてから実施する。アップデート後すぐに管理画面へアクセスできるか、フロントエンドにエラーが出ていないかを確認し、問題があればすぐに旧バージョンへロールバックできるよう、ファイルのバックアップを手元に残しておく。

よくある質問

myCred 本体をアップデートしていないと同様のエラーは起きるか

プラグインによっては、本体(myCred コア)とアドオン(Toolkit Pro)のバージョンに互換性が要求される。MWP_Module クラスは Toolkit Pro 内部の抽象クラスなので myCred コアのバージョンに直接は依存しないが、コアが古すぎると別の非互換エラーを引き起こす可能性がある。常に両方を最新に保つことが望ましい。

修正版が出るまでサイトを止めておくべきか

致命的エラーでサイトが完全に停止しているなら、前述の緊急復旧手順でプラグインを無効化するか旧バージョンへ巻き戻し、通常運用を再開してよい。ポイント機能が止まる影響を考慮し、必要なら代替手段を顧客に案内する。

エラーログはどこで確認できるか

WordPress のデバッグモードを有効にしていれば /wp-content/debug.log にエラー詳細が出力される。有効でない場合は wp-config.phpdefine( 'WP_DEBUG', true );define( 'WP_DEBUG_LOG', true ); を記述する。レンタルサーバーによってはエラーログが管理画面から閲覧できる場合もある。

子テーマの functions.php で読み込み順序を修正できるか

テーマの functions.php はプラグインより後に読み込まれるため、この方法では MWP_Module クラスを事前に定義することはできない。プラグインファイルの直接編集が必須になる。

この記事のポイント

  • myCred Toolkit Pro アップデート後の MWP_Module クラス欠落エラーは、読み込み順序の不備が主因
  • 緊急復旧は FTP でプラグインフォルダをリネームし、旧バージョンへ差し替える
  • 手動修正では子クラスのファイル冒頭に require_once を追加する
  • 開発元修正版を適用する際は必ずバックアップとステージング検証を行う
  • PHP のオートローダー設定や Composer のクラスマップ再生成も有効なアプローチ
Shield SecurityのcookieがNginxキャッシュを止める時の解決策

Shield SecurityのcookieがNginxキャッシュを止める時の解決策

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

なぜ Shield Security が全ページでキャッシュを止めてしまうのか

なぜ Shield Security が全ページでキャッシュを止めてしまうのか

Shield Security はボット判定や silentCAPTCHA の動作のために icwp-wpsf-notbot という cookie をフロントエンドの全ページで発行する仕様になっている。Nginx のキャッシュ機構は原則として Set-Cookie ヘッダを含むレスポンスをキャッシュしないため、この cookie がすべてのページキャッシュを無効化してしまう。結果として x-proxy-cache: MISS が返り続け、サーバーへのリクエストが毎回発生し、レスポンスタイムが 1000ms を超える状況に陥る。

Before(Shield 有効時)
リクエストのたびに Set-Cookie が発生
Nginx はレスポンスをキャッシュせず破棄
レスポンスタイム 1000ms〜1600ms
After(cookie 停止後)
キャッシュ可能なレスポンスが返る
初回 MISS → 2回目以降 HIT で高速表示
レスポンスタイム 約100ms
cookie がキャッシュを妨害している状態  cookie 停止後

サーバー側で特定の cookie だけをキャッシュ対象から除外する設定ができない場合、プラグイン側でこの cookie を止めるのが唯一の現実的な解決策になる。

管理画面で silentCAPTCHA の複雑度を「なし」にする

管理画面で silentCAPTCHA の複雑度を「なし」にする

Shield Security の silentCAPTCHA は、ボット防御のためにフロントエンドのページにも cookie をセットする。設定を最小限に絞り込むには、まず管理画面から操作する。

STEP 1 WordPress 管理画面 → 左メニュー「Shield」→「設定」
STEP 2 「CAPTCHA」タブを開き「silentCAPTCHA」セクションを探す
STEP 3 「複雑度」を なし に変更して保存
STEP 4 「ログイン保護」「スパムボットブロック」などで不要な silentCAPTCHA の利用をすべてオフにする

これだけでは cookie の出力が止まらないケースが多い。Shield は silentCAPTCHA の設定に関わらず、フロントエンドの訪問者に対して一律に icwp-wpsf-notbot をセットする内部ロジックを持っているためだ。ここから先はコードレベルの対応が必要になる。

フィルターフックで匿名ユーザーへの cookie 送信を無効化する

フィルターフックで匿名ユーザーへの 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 の値を確認する
  • プラグインのアップデート後はフィルター名の変更に注意しキャッシュを完全クリアして再テストする