PHP 8における型ヒントの不一致エラー「Fatal error: Uncaught TypeError: Argument 1 passed to processData() must be of type int, string given」の解決

intermediate🐘 PHP2026-03-26

TL;DR: クイック修正

このTypeErrorは、PHPコードがint(またはboolfloatのような別のスカラー型)を明示的に期待する関数にstringを渡そうとしていることを示しています。

これを解決するには、通常、2つの主要なアプローチがあります。

  • 入力データの強制型変換: 渡す変数が期待される型であることを確認します。例えば、関数を呼び出す(int)$myStringを使用して文字列を整数にキャストします。これは多くの場合、最も簡単で正しい解決策です。
  • 関数の型ヒントの調整: 関数が常に文字列を受け入れることを意図していた場合、その型宣言を更新します。関数のシグネチャでintstringに変更します。

問題のある行(例: /var/www/html/app.php on line 42)と関数(processData())を素早く特定します。次に、上記で説明した修正のいずれかを適用して、差し迫った問題を解決します。

発生事象: PHP 8でのUncaught TypeError

午前2時、重要なサービスが予期せずクラッシュしたと想像してください。ログを確認すると、次のような不穏なメッセージが見つかります。

Fatal error: Uncaught TypeError: Argument 1 passed to processData() must be of type int, string given, called in /var/www/html/app.php on line 42

これはメモリリークやファイルが見つからないエラーではありません。代わりに、TypeErrorであり、特に型の不一致を強調しています。このエラーは、関数引数に提供されたデータ型が期待される型と一致しないことを示しています。PHP 8は、以前のバージョンよりもデフォルトで厳密なスカラー型チェックを強制するため、コードベースが完全に型安全でない場合、これらの種類のエラーがより頻繁に発生します。

エラーの再現

このエラーを引き起こす簡単なコード例を見てみましょう。

<?php

declare(strict_types=1); // PHP 8ではTHISエラーの場合(損失のある変換のため)厳密には必要ないが、厳密性を強調している。

function processData(int $data): string
{
    return "Processed: " . ($data * 2);
}

$userInput = "123abc"; // これは文字列だが、数値として処理したい。

// この行がTypeErrorを引き起こす
echo processData($userInput); // app.php on line 42

?>

このスクリプトが実行されると、PHPはprocessData()関数内の$dataの型ヒントを調べます。intを期待していますが、string(具体的には"123abc")を受け取ります。PHP 8はデータ損失につながる型変換についてより厳密であるため、すぐにTypeErrorをスローし、スクリプトの実行を停止します。

根本原因分析

この問題の核心は、関数の定義された契約に違反していることにあります。PHP 7では、明示的にdeclare(strict_types=1);を使用しない限り、スカラー型ヒントはしばしば緩やかに強制されていました。PHP 8では、大きな変更が導入されました。

PHP 8以降、スカラー型宣言はより厳密に強制されます。これは、内部関数に対してはデフォルトで適用され、データ損失なしに値を強制型変換できない場合(非数値文字列を整数に変換する場合など)はユーザー定義関数に対しても適用されます。呼び出し元のスコープでもdeclare(strict_types=1);が有効になっている場合、損失のない型不一致であってもすべてTypeErrorがスローされます。

エラーメッセージを分解してみましょう。

  • Fatal error: Uncaught TypeError: 型の不一致のため、スクリプトが突然停止しました。
  • Argument 1 passed to processData(): 問題はprocessData関数に提供された最初の引数にあります。
  • must be of type int, string given: 関数は整数を期待していますが、代わりに文字列を受け取りました。
  • called in /var/www/html/app.php on line 42: これは、問題のある関数呼び出しが発生した正確なファイルと行番号を特定します。

要するに、processData関数はint $dataという型ヒントで宣言されており、$dataに渡される値が整数でなければならないことをPHPに示しています。しかし、コードの42行目では、このパラメーターに文字列("123abc")を渡そうとしており、致命的なエラーが発生しています。

解決策

このTypeErrorを解決するにはいくつかのオプションがあり、最適な選択肢はコードの意図された動作によって異なります。

1. 入力データの強制型変換 (最も一般的で推奨される方法)

processData()が本当に整数のみを処理するように設計されている場合、主な目標は、それがintを受け取ることを確実にすることです。このシナリオは、ユーザー入力の処理、APIレスポンスの解析、または数値データを文字列として配信する可能性のある外部ソースからのデータの処理で頻繁に発生します。

修正例: intへのキャスト

<?php

declare(strict_types=1);

function processData(int $data): string
{
    return "Processed: " . ($data * 2);
}

$userInput = "123abc"; // まだ文字列

// オプションA: intへの明示的なキャスト。"123abc"は123になる。
$processedInput = (int)$userInput;
echo processData($processedInput) . "\n";

// オプションB: intval()を使用。同様の効果で、これも123に変換される。
// echo processData(intval($userInput)) . "\n";

// オプションC: 厳密に数値の文字列を期待し、それを検証したい場合
if (is_numeric($userInput)) {
    echo processData((int)$userInput) . "\n";
} else {
    echo "Error: Invalid numeric input provided. Expected a number, got '$userInput'." . "\n";
}

?>

説明: (int)キャストは、文字列を整数に変換しようとします。"123abc"のような文字列の場合、最初の数値文字以降の非数値文字は破棄され、123に変換されます。文字列に先頭の数値文字がない場合(例: "hello world")、0に変換されます。データ整合性が重要である場合は、この変換動作に常に注意し、ユーザー入力を徹底的に検証してください。

2. 関数の型ヒントの調整 (ヒントが間違っていた場合)

おそらく、processData()関数は常に文字列、あるいは複数のデータ型を処理することを意図していました。そのような場合、既存の型ヒントは単に間違っており、修正が必要です。

修正例: intstringに変更する

<?php

declare(strict_types=1);

// 関数は今、正しく文字列を期待する
function processData(string $data): string
{
    // これで、関数内で文字列データを適切に処理する必要がある。
    // 数値処理がまだ必要な場合は、検証や変換が必要になるかもしれない。
    if (is_numeric($data)) {
        return "Processed numeric string: " . ((int)$data * 2) . "\n";
    } else {
        return "Processed non-numeric string: " . $data . "\n";
    }
}

$userInput = "123abc";
echo processData($userInput);

$anotherInput = "hello world";
echo processData($anotherInput);

?>

説明: この戦略は、関数が受け取るように設計されたデータを正確に反映するように、関数の契約を変更します。これは、元の型ヒントが間違いであった場合、または関数の要件が変化した場合に理想的な修正です。

3. 複数の型を許可 (PHP 8 Union Types)

関数が本当に複数のスカラー型を受け入れる必要がある場合、たとえばintまたはstringのいずれかを適切に処理できる場合、PHP 8のUnion Typesはクリーンで表現力豊かなソリューションを提供します。

修正例: Union Types (int|string) の使用

<?php

declare(strict_types=1);

// 関数は今、intまたはstringのいずれかを受け入れる
function processData(int|string $data): string
{
    if (is_int($data)) {
        return "Processed int: " . ($data * 2) . "\n";
    } elseif (is_string($data)) {
        // 文字列データを処理。数値であれば変換する可能性がある
        if (is_numeric($data)) {
            return "Processed numeric string: " . ((int)$data * 2) . "\n";
        } else {
            return "Processed non-numeric string: " . $data . "\n";
        }
    }
    // この行は、適切に定義されたユニオン型ヒントがあれば理想的には到達しないはず。
    return "Invalid input type encountered." . "\n"; 
}

$userInputString = "123abc";
echo processData($userInputString);

$userInputInt = 456;
echo processData($userInputInt);

?>

説明: int|string宣言は、intまたはstringのいずれかが許容される引数であることをPHPに伝えます。関数内では、is_int()is_string()、またはinstanceofのような条件チェックを使用して、実際の型を判断し、それに応じて処理します。

4. nullを許可 (Nullable Types)

引数が省略されたり、明示的にnullとして渡されたりする可能性があるシナリオでは、型ヒントをnull許容にすることができます。これはオプションのパラメーターに役立ちます。

修正例: Nullable Type (?int) の使用

<?php

declare(strict_types=1);

// 関数はintまたはnullを受け入れることができる
function processData(?int $data): string
{
    if ($data === null) {
        return "No data provided.\n";
    }
    return "Processed: " . ($data * 2) . "\n";
}

$userInput = null;
echo processData($userInput);

$validInput = 123;
echo processData($validInput);

// これは常にTypeErrorを引き起こす。なぜなら"123abc"はintでもnullでもなく、
// strict_types=1がなくてもデータ損失なしにintに強制変換できないため。
// echo processData("123abc"); 

?>

説明: 型の前の?プレフィックス(例: ?int)は、引数が宣言された型(この場合はint)またはnullのいずれかであることを許可します。これにより、オプションのデータに対して柔軟性が提供されます。

検証手順

推奨される修正のいずれかを適用したら、すべてが正しく機能していることを確認するために、次の手順に従ってください。

  • PHP Opcacheのクリア: 環境でopcache(OPcacheなど)を使用している場合は、必ずクリアしてください。または、PHP-FPMサービスまたはWebサーバー(例: sudo systemctl restart php8.2-fpm)を再起動して、更新されたコードをロードします。
  • スクリプトの実行: app.phpスクリプトを再度実行します。Webアプリケーションの一部である場合は、ブラウザで関連するページを更新します。
  • エラーの確認: Fatal error: Uncaught TypeErrorメッセージが表示されなくなったことを確認します。Webサーバーのエラーログ(例: Apacheエラーログ、Nginxエラーログ)およびPHP-FPMログを確認してください。
  • 出力の検証: 最後に、アプリケーションが期待どおりに動作することを確認します。新しいエラーを発生させることなく、正しい出力が生成されているか、意図されたアクションが実行されていることを確認します。

参考文献

Related Error Notes