問題の概要最近、PHP 7.4から8.2への移行作業中に、チームメイトと私はレガシーなコードベースで壁に突き当たりました。ホームページは完璧に表示されましたが、ユーザーダッシュボードが即座にクラッシュしたのです。エラーログを確認したところ、犯人が判明しました。
Fatal error: Uncaught Error: Non-static method User::getName() should not be called statically
PHP 5.6や7.xの時代、この間違いは通常 Deprecated 警告や Notice を発生させるだけでした。コードが乱雑であっても、スクリプトの実行は継続されていました。しかし、2020年11月の PHP 8.0 のリリース以降、これは Fatal Error(致命的エラー) に格上げされました。現在では、アプリケーションが完全に停止する原因となります。
エラーが発生する理由このエラーは、static キーワードで定義されていないメソッドに対して、スコープ定義演算子(Class::method())を使用した場合に発生します。オブジェクト指向プログラミングにおいて、非静的メソッドは特定の インスタンス(オブジェクト)に属しますが、静的メソッドは クラス定義 そのものに属します。
以下は、PHP 8でサイトをクラッシュさせるコードのスニペットです。
class User {
public function getName() {
return "山田 太郎";
}
}
// PHP 8.0以降では致命的エラーが発生します
echo User::getName();
解決策この問題を解決するには、メソッドが内部のオブジェクトデータにアクセスする必要があるかどうかに応じて、主に2つの方法があります。
方法 1:クラスをインスタンス化する(インスタンスデータに最適)メソッド内で $this を使用してプロパティにアクセスしている場合は、まずオブジェクトを作成する必要があります。これはドメインモデルやほとんどのアプリケーションロジックにおける標準的なアプローチです。
class User {
private $name = "山田 太郎";
public function getName() {
return $this->name;
}
}
// 正しい方法:オブジェクトを作成してからメソッドを呼び出す
$user = new User();
echo $user->getName();
方法 2:メソッドを静的(static)として宣言するメソッドが内部のオブジェクト状態に依存しない「純粋な」ヘルパー関数の場合は、この修正方法を使用します。static キーワードを追加することで、クラスから直接呼び出せることを PHP に伝えます。
class User {
public static function getName() {
return "山田 太郎";
}
}
// これで正常に動作します
echo User::getName();
「$this」の罠に注意方法2を選択する際は注意が必要です。$this を含んだままのメソッドに static キーワードを追加すると、即座に別のエラー Uncaught Error: Using $this when not in object context が発生します。静的メソッドには、インスタンスにおける「自分自身」という概念がありません。プロパティへのアクセスが必要な場合は、方法1を選択してください。
親クラスの呼び出しの処理レガシーコードでは、継承の際にこのエラーが発生することがよくあります。非静的な親メソッドを静的な形式の構文で呼び出すことができるのは、すでに非静的な子メソッドの中にいる場合のみです。
class Base {
public function log() { /* ... */ }
}
class Child extends Base {
public function doWork() {
// doWork() も非静的であるため、これのみ動作します
parent::log();
}
}
動作確認CLIでスクリプトを実行するか、ブラウザをリフレッシュして修正をテストしてください。本番環境に反映される前にこれらの問題をキャッチするには、php.ini ファイルでエラーレポートを最高レベルに設定してください。
error_reporting(E_ALL);
ini_set('display_errors', 1);
ページが致命的エラーなしでレンダリングされ、データが正しく表示されれば完了です。

