PHP8で発生するTypeErrorエラーへの対処法

PHP8へのバージョンアップに伴い、これまで曖昧に許容されていた引数の型が厳格にチェックされるようになりました。
本記事では、よく遭遇する「Fatal error: Uncaught TypeError: Argument xxxx must be of type …」というエラーの原因や解決策について、いくつかの具体例とともに説明します。
これを読めば、PHP8特有の型エラーメッセージへの対処法や、コードリファクタリングのポイントを把握できるようになります。

目次

PHP8で発生するTypeErrorとは何か

PHP8では型システムが強化され、引数や戻り値の型に合わない値が渡された場合、TypeErrorが即座にスローされます。
これにより、従来は不正な型変換が起きていてもエラーにならなかった場面で、実行時に明示的なエラーが発生するようになったのです。
「Argument xxxx must be of type YYY」のようなエラーメッセージは、関数やメソッドに指定した型ヒントに反した引数が渡されていることを示しています。

例: 引数がint型を要求している関数にstringを渡すケース

次のような関数を考えます。

function multiplyByTwo(int $number): int {
return $number * 2;
}

PHP7以前でもstrict_types=1を指定していない限り、"10"のような文字列を渡しても自動的にintへキャストされ、動作してしまう場面がありました。
しかし、PHP8では以下のようなコードはTypeErrorが発生します。

echo multiplyByTwo("10");

実行結果:

Fatal error: Uncaught TypeError: Argument #1 ($number) must be of type int, string given

このエラーから分かるように、渡された引数が指定の型と合わない場合には明確なエラーメッセージが出力されます。

PHP8でよくあるTypeErrorの発生パターン

プリミティブ型同士の不一致

関数やメソッドがintstringといったプリミティブ型を受け取るとき、異なるプリミティブ型を渡すと直ちにTypeErrorが起きます。
これは従来のPHPが内部的に暗黙的な型変換を行っていた挙動と大きく異なります。

オブジェクト型の不一致

指定されたクラスやインターフェースのインスタンスでないものが渡された場合もTypeErrorが発生します。
例えば、以下のようなコードを想定します。

interface LoggerInterface {
public function log(string $message): void;
}

class FileLogger implements LoggerInterface {
public function log(string $message): void {
// ファイルへログを書き込む処理
}
}

function writeLog(LoggerInterface $logger, string $message) {
$logger->log($message);
}

// 本来はLoggerInterfaceを実装したインスタンスを渡すべき
writeLog(new stdClass(), "テストメッセージ");

このコードを実行すると、

Fatal error: Uncaught TypeError: Argument #1 ($logger) must be of type LoggerInterface, stdClass given

というエラーが発生します。
このように、インターフェースやクラス型を明示している場合に、その型を満たさない引数が渡されると厳密なエラーとして通知されます。

対策と解決方法

渡す引数の型を再確認する

最も基本的な対処法は、エラーメッセージに示される引数が要求する型を確認し、実際に渡している値の型が適切か再チェックすることです。
例えば、intが必要なのにstringを渡している場合は、予め(int)$valueとキャストする、または受け取り側のロジックを変更して正しい型を提供するようにします。

nullやオプション引数の扱い

PHP8では、型付き引数にnullを渡す場合にも注意が必要です。
nullを許可したい場合は、型宣言を?int?stringのようにnullable型にする必要があります。
nullable指定が無い場合にnullを渡すとTypeErrorが発生します。

型宣言の見直し

もしも引数が多様な型を受け付ける必要がある場合は、ユニオン型(int|stringのような宣言)を用いるか、別のメソッドに分離して明確な役割分担を行うことができます。
PHP8からはユニオン型が導入されているため、複数の型を引数として許容したい場合はこの機能を活用できます。

テストと型チェックツールの活用

PHPCSやPHPStan、Psalmなどの静的解析ツールを用いて型チェックを強化することも有効です。
コードを書く段階で不正な型渡しが無いか検知できるため、本番実行時にエラーが出る前に問題点を修正できます。
このようなツールをCI環境に組み込み、自動的に型の整合性を保証する流れを構築することがおすすめです。

まとめ

PHP8で導入された厳密な型チェックにより、これまで曖昧に処理されていた型不整合が明確なエラーとして表面化するようになりました。
この変更は、コードの品質向上やバグの早期発見につながる一方で、既存コードをPHP8へ移行する際にはTypeErrorの対応が必要になります。
本記事で紹介した例や対処法(引数の型見直し、nullable対応、ユニオン型の活用、静的解析ツールの活用など)を参考に、エラーが発生した際には問題個所を素早く特定し、コードベースを堅牢なものへアップデートしていくことが可能です。
これらの手順を踏むことで、PHP8への移行や新規開発時にも、型に関連するエラーを円滑に解決できるようになります。

関連記事

あわせて読みたい
PHP7からPHP8への移行でよく発生する警告・エラー10選とその対応方法 本記事では、PHP7からPHP8への移行を行う際によく遭遇する警告やエラーを10項目ピックアップし、PHP7とPHP8での差異を踏まえて詳しく解説します。それぞれのケースにつ...
よかったらシェアしてね!
  • URLをコピーしました!
目次