タグアーカイブ fatal error

WC Vendors 2.7.0アップグレードでfatal errorが出た時の対処法

WC Vendors 2.7.0アップグレードでfatal errorが出た時の対処法

WC Vendors 2.7.0 にアップグレードした直後、サイト全体が「このサイトで重大なエラーが発生しました」の表示になり管理画面にもアクセスできなくなった場合、wcvendors_capability_product_types オプションの値が配列ではなく文字列で保存されていることが原因だ。WP-CLI を使えるかどうかで復旧手順を分けて対処する。

WC Vendors 2.7.0で管理画面にすら入れなくなる原因は何か

WC Vendors 2.7.0で管理画面にすら入れなくなる原因は何か

この問題は、プラグイン内部の関数 wcv_is_all_product_types_hidden()array_diff() を呼び出す際、引数として文字列を渡してしまうことで発生する。PHP 8 環境では型宣言が厳密になったため、ここで TypeError(致命的エラー)が起こり、サイト全体が HTTP 500 エラーで停止する。

関数に渡されるのは wcvendors_capability_product_types というオプションの値だ。このオプションは本来、商品タイプの配列(['simple', 'variable'] など)を保持すべきだが、古いバージョンの WC Vendors(特に 1.x 系)から移行してきたサイトでは、内部的に「simple」のような文字列のまま残っているケースがある。2.7.0 で追加された新しい関数には配列へのキャスト処理が含まれておらず、長期間眠っていた不正なデータが一気に致命的エラーとして表面化した。

2.5.1.1 以前
(array) によるキャストがあり、文字列でも配列として扱われていた
→ エラーは表面化せず、サイトは通常通り稼働
2.7.0 アップグレード後
array_diff() に文字列が直接渡され、PHP 8 で TypeError
→ サイト全体が HTTP 500 エラー、管理画面も開けない
エラー発生 正常動作

エラーのトリガーは wp_loaded フックで、これは WordPress の読み込みのかなり早い段階で実行される。そのため管理画面もフロントエンドも一切表示されず、ダッシュボードからプラグインを無効化するという通常の復旧手段が使えなくなってしまう。

管理画面にログインできない場合の応急処置(WP-CLI を使う)

管理画面にログインできない場合の応急処置(WP-CLI を使う)

サーバーに SSH でアクセスできる環境であれば、WP-CLI を使って不正なオプション値を直接修正するのが最も確実な回復方法だ。管理画面に入れなくても、この操作でサイトは即座に復旧する。

STEP 1 SSH でサーバーに接続する
STEP 2 WordPress のインストールディレクトリに移動する
STEP 3 以下のコマンドを実行し、オプションを配列形式で上書きする
STEP 4 サイトの表示を確認する
wp option update wcvendors_capability_product_types '["simple"]' --format=json

上記コマンドは wcvendors_capability_product_types オプションの値を強制的に JSON 配列として上書きする。["simple"] の部分は、自サイトで実際に有効にしていた商品タイプのスラッグに置き換える。可変商品や外部商品を使っていた場合は、["simple","variable","external"] のようにカンマ区切りで列挙する。値は連想配列ではなく、単純なリスト形式でなければならない。

WP-CLI を使えない場合のエラー復旧手順(FTP/ファイルマネージャー)

WP-CLI を使えない場合のエラー復旧手順(FTP/ファイルマネージャー)

レンタルサーバーでは SSH が利用できず、WP-CLI も使えないケースが多い。その場合は FTP またはサーバー付属のファイルマネージャーを使ってプラグインを一時的に無効化し、管理画面にアクセスできる状態に戻す。

  1. FTP クライアントまたはファイルマネージャーで /wp-content/plugins/ ディレクトリにアクセスする
  2. wc-vendors ディレクトリを探し、名前を wc-vendors-disabled に変更する
  3. ブラウザで管理画面の URL(yourdomain.com/wp-admin/)を開く
  4. 管理画面にログインできたら、wc-vendors-disabled をもとの wc-vendors に戻す(ただし有効化はしない)
  5. 管理画面の「プラグイン」で WC Vendors が「無効」になっていることを確認し、データベースの該当オプションを修正する手順に進む

ディレクトリ名の変更によってプラグインが強制的に無効化される仕組みを利用している。ファイル自体は削除せず、リネームするだけなので元に戻せる。管理画面に戻ったら、次のセクションで説明する根本的なオプション修正を行う。現時点で WC Vendors を再度有効化すると、同じエラーが再発するので有効化してはいけない。

根本的な修正をプラグインのアップデート前に済ませておく

根本的な修正をプラグインのアップデート前に済ませておく

WC Vendors の開発チームはこの問題を認識しており、将来のリリースで修正が反映される見込みだ。しかしアップデートを待つだけでは、同じサイトで別の箇所が再び同様のエラーを起こす可能性を抱えたままになる。管理画面にログインできる状態にしたら、データベース上のオプション値を正規化してしまおう。

最も簡便な方法は、先ほど WP-CLI で実行したコマンドと同じ操作を、データベース管理ツール(phpMyAdmin など)やカスタムスクリプトで行うことだ。具体的には wp_options テーブルを開き、option_namewcvendors_capability_product_types の行を探す。option_value カラムが文字列(例 simple)になっている場合、a:1:{i:0;s:6:"simple";} のようにシリアライズされた配列表現に書き換える。

PHP のシリアライズ形式を手書きするのはミスが怖い場合は、次のような安心な手順をとる。

  1. WC Vendors が無効化されていることを確認する
  2. 管理画面の「設定」→「WC Vendors」→「販売」→「商品タイプ」に進み、チェックボックスで適切な商品タイプを選んで保存する(これで正常な配列としてオプションが上書きされる)
  3. WC Vendors を有効化する

この方法は管理画面を使うため、データベースを直接触る必要がなく安全だ。ただしバージョン 2.7.0 では有効化した瞬間に wp_loaded フックのエラーが再発する可能性があるため、あらかじめプラグインファイルの該当行を一時的に修正するか、前述のキャストを適用しておくと確実だ。

よくある質問

エラーログを確認するにはどうすればよいか

サーバーのエラーログには wp-content/debug.log(WordPress のデバッグログ)や、Apache/Nginx のエラーログがある。WP-CLI が使えれば wp config set WP_DEBUG true --rawwp config set WP_DEBUG_LOG true --raw でログ出力を有効にした上で、エラーを再現させて wp-content/debug.log を確認する。共有サーバーではホスティングの管理画面からエラーログが見られることも多い。

WC Vendors をアップグレードする前に何か注意すべきことはあるか

メジャーバージョンアップを行う場合は、本番サイトに適用する前に必ずステージング環境でテストする。どうしても本番で行うなら、事前にデータベースのバックアップを取り、wcvendors_capability_product_types オプションの現在の値を確認しておく。WP-CLI で wp option get wcvendors_capability_product_types --format=json を実行し、値が配列形式になっていることを確かめればリスクを大幅に減らせる。

PHP のバージョンが 7.x 系ならこの問題は起きないか

PHP 7.x では array_diff() に文字列を渡しても Warning は出るが Fatal Error にはならないため、サイトが完全停止することはない。ただしエラー自体の根本原因は同じであり、動作は予期しない結果になる可能性が高い。推奨される PHP のバージョンは 8.x 系へ移行することであり、その前に対処しておくことが望ましい。

WC Vendors Free と Pro のどちらでも発生するのか

この問題は WC Vendors の無料版(Free)のコア機能部分で発生している。Pro 版を併用している場合でも、同じオプション値を読み込むため影響を受ける可能性が高い。特に 1.x 系からバージョンを重ねてきたサイトは要注意だ。

この記事のポイント

  • WC Vendors 2.7.0 へのアップグレードでサイトが停止するのは array_diff() の型不一致が原因
  • 古いサイトでは wcvendors_capability_product_types が文字列で残っているケースがある
  • WP-CLI を使えるなら wp option update で即座に復旧できる
  • WP-CLI が使えない場合はプラグインディレクトリをリネームして管理画面に復帰する
  • 根本的には設定画面で商品タイプを保存し直すか、データベースの値を配列に正規化する

特定商品ブロックを設置した固定ページでfatal errorが発生する問題の直し方

特定商品ブロックを固定ページに配置したときに「Uncaught Error Call to a member function get_id() on null」というfatal errorが表示されるのは、PreCart for WooCommerce のバグが原因だ。プラグインを最新バージョンへ更新するか、functions.php へ一時的な修正コードを追加すれば直る。

なぜ固定ページ上の商品ブロックで fatal error が起こるのか

なぜ固定ページ上の商品ブロックで fatal error が起こるのか

PreCart は WooCommerce の商品情報を扱うフィルターフック(woocommerce_product_add_to_cart_text など)にコールバック関数を登録し、その中で global $product から商品オブジェクトを取得して $product->get_id() を呼び出している。しかし、ブロックエディタで「特定商品」ブロックを通常の固定ページに配置すると、WooCommerce のブロック表示パイプラインではグローバル変数 $product が null のままフィルターが走るケースがある。PreCart のコードには null チェックがないため、null に対して get_id() を呼び出してしまい、致命的なエラーでページ全体が落ちる。

STEP 1 固定ページに「特定商品」ブロックを追加し任意の商品を選択
STEP 2 WooCommerce ブロック描画時に PreCart のフィルターが発火
STEP 3 グローバル変数 $product が null のままコールバックが実行される
STEP 4 $product->get_id() で致命的エラー発生(画面が真っ白になる)

影響を受けるメソッドは change_add_to_cart_text()display_pre_order_messgae()display_pre_order_badge() など、いずれも保護コードがない。WooCommerce の商品ブロックを店舗ページ以外で使っているサイトはすべてこの問題に遭遇し得る。

PreCart を更新してエラーを解消する手順

PreCart を更新してエラーを解消する手順

開発元はこの問題を認識しており、すでに修正アップデートがリリースされている。まずは管理画面からプラグインを最新版に上げるのが最も安全で確実な対処法だ。

STEP 1 WordPress 管理画面へログインし「プラグイン」→「インストール済みプラグイン」を開く
STEP 2 PreCart for WooCommerce に更新通知が出ていたら「今すぐ更新」をクリック
STEP 3 サイトのキャッシュ(プラグインキャッシュ、サーバーキャッシュ)をすべて削除
STEP 4 問題のあった固定ページをフロントエンドで再度開き、エラーが出ないことを確認

更新通知が表示されない場合

「ダッシュボード」→「更新」から更新の再確認を行うか、PreCart のプラグインページで一度「プラグインを削除」→ 公式リポジトリから再インストールする方法もある。ただしこの場合、設定がリセットされる可能性があるため、事前に PreCart の設定をメモしておくかエクスポート機能があれば使っておくと安心だ。

functions.php で null チェックを追加して一時的に対処する方法

functions.php で null チェックを追加して一時的に対処する方法

どうしてもすぐにプラグインを更新できない場合や、何らかの理由で更新後に問題が残る場合は、テーマの functions.php にフックを追加して一時的にエラーを回避できる。

/**
 * PreCart の null チェック不足による fatal error を回避(一時的対応)
 */
add_filter( 'woocommerce_product_add_to_cart_text', function( $text, $product ) {
    if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
        return $text;
    }
    // 以下は原本の処理が走るが、早期リターンで保護
    return $text;
}, 1, 2 );

add_filter( 'woocommerce_single_product_summary', function() {
    global $product;
    if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
        return;
    }
    // 同様に早期リターン
}, 1 );

上記のコードは PreCart が使っているのと同じフックに、より優先度の高いコールバック(優先度 1)で null チェックを追加し、商品オブジェクトが存在しないときは処理を打ち切る仕組みだ。PreCart のフィルターよりも先に実行されるため、致命的エラーに至る前に関数を抜けられる。

Before(危険)
global $product;
$product->get_id();
null チェックがないためエラー
After(安全)
if ( ! $product || ! is_a( $product, ‘WC_Product’ ) ) { return; }
$product->get_id();
null のときは早期リターン
修正前  修正後

functions.php 編集時の注意点

子テーマを使っていない場合、テーマ更新で修正が上書きされるリスクがある。必ず子テーマの functions.php にコードを追加するか、Code Snippets プラグインでコードを管理するのが望ましい。また、この一時対応はあくまで応急処置であり、PreCart の他の機能が正常に動作しない可能性もゼロではない。早めに公式アップデートを適用して、追加コードは削除する。

手動修正後に確認しておきたいポイント

手動修正後に確認しておきたいポイント
  • 一時的なコードを追加した後、サイトの表示速度やエラーログに変化がないか定期的にチェックする
  • PreCart の機能(カート追加テキストの変更や予約注文バッジなど)が期待どおり動作しているかテストする
  • PHP のエラーログを確認し、別の箇所で同様の null 参照エラーが隠れていないか調べる
  • サイト全体のキャッシュをクリアし、CDN を利用している場合は CDN キャッシュも破棄する
  • PreCart の更新が確認できたら必ずプラグインを最新版に上げ、追加コードを削除する

よくある質問

PreCart 以外のプラグインでも同じように商品ブロックでエラーが出ることはありますか

ある。WooCommerce のブロックを通常ページで使うと、$product グローバルを正しく取り扱っていない他の拡張プラグインでも同様の null 参照エラーが起きるケースが報告されている。エラーの文面に別のプラグイン名が含まれている場合は、そちらの開発元へ報告しつつ、同じように functions.php で早期リターンを追加すれば応急回避できることが多い。

WooCommerce の商品ブロックを固定ページで使うこと自体は問題ないのでしょうか

WooCommerce のブロックは基本的に店舗ページや商品ページで使うことを想定しているが、WordPress の標準ブロックとして技術的にはどの投稿タイプでも利用できる。プラグインがグローバル変数の有無を適切にハンドリングしていれば固定ページで使っても問題は起きない。ただ、テーマやプラグインが認めるまで、動作確認は入念に行ったほうがよい。

エラーメッセージが表示されずに画面が真っ白になる場合はどうすればよいですか

WordPress が致命的エラーを表示しない設定(WP_DEBUG が false)のときは、管理画面のメールに送られる復旧モード用のリンクを探すか、サーバーの PHP エラーログを確認する。wp-config.php で define('WP_DEBUG', true); を一時的に有効にすれば、画面上にエラー詳細が表示され、原因を特定しやすくなる。なお、本番環境ではデバッグモードをすぐに無効に戻すこと。

管理画面にも入れなくなってしまった場合はどうすれば直りますか

FTP またはレンタルサーバーのファイルマネージャーで /wp-content/plugins/precart/ ディレクトリの名前を一時的に変更(例:precart_deactivated)すれば、プラグインが無効化されて管理画面に再ログインできる。その後、前述の更新や一時コードで対処し、ディレクトリ名を元に戻す。

この記事のポイント

  • 固定ページに WooCommerce 商品ブロックを配置したときの fatal error は PreCart の null チェック不足が原因
  • 解決策は PreCart プラグインの最新版への更新が最も安全で確実
  • すぐに更新できない場合は、functions.php にフックで早期リターンを追加すれば応急回避できる
  • functions.php 編集は子テーマで行い、アップデート後は必ず追加コードを削除する
  • 管理画面に入れなくなったら FTP でプラグインフォルダ名を変更し無効化する