エラーの内容
関数を呼び出す際に、必須の引数を1つ以上省略しました。PHPはその場で実行を停止し、以下のエラーをスローします:
Fatal error: Uncaught ArgumentCountError: Too few arguments to function update_user(), 1 passed and exactly 2 expected
実行はその場で終了します。PHP 7以降、このエラーは単なる警告から本格的な ArgumentCountError へと格上げされました。そのため、PHP 5で静かに「動いていた」コードは、今では確実にクラッシュします。
根本原因
呼び出し元が、関数のシグネチャが要求するすべての引数を渡していません。ほとんどのケースは2つの原因に集約されます。マージや更新後に関数に新しい必須パラメータが追加されたか、最初から呼び出しが不完全だったのにPHP 5が単に警告を出さなかったかです。
このエラーを引き起こす例:
<?php
function update_user(int $user_id, string $name): bool {
// DBのユーザーを更新する
return true;
}
// 誤り — 引数を1つしか渡していない
update_user(42);
// Fatal error: Too few arguments to function update_user(), 1 passed and exactly 2 expected
修正1:不足している引数を渡す
関数のシグネチャが実際に何を必要としているか確認し、必要なものをすべて渡します:
<?php
// 正しい — 必須の引数を両方渡す
update_user(42, 'John Doe');
関数がどのパラメータを取るかわからない場合、リフレクションで各パラメータと省略可能かどうかを表示できます:
<?php
$ref = new ReflectionFunction('update_user');
foreach ($ref->getParameters() as $param) {
echo '$' . $param->getName();
if ($param->isOptional()) {
echo ' (省略可能, デフォルト: ' . var_export($param->getDefaultValue(), true) . ')';
} else {
echo ' (必須)';
}
echo "\n";
}
修正2:パラメータを省略可能にする
不足している引数に適切なデフォルト値がある場合、関数のシグネチャで宣言することで、呼び出し元が渡す必要がなくなります:
<?php
function update_user(int $user_id, string $name = ''): bool {
if ($name === '') {
// DBから取得するか、名前の更新をスキップする
}
return true;
}
// どちらも動作する
update_user(42); // デフォルトの空文字列を使用
update_user(42, 'John'); // 指定した名前を使用
空またはnullのデフォルト値が本当に意味をなす場合にのみ使用してください。データの欠落を隠蔽するために使わないでください。
修正3:可変長引数の構文を使用する
関数が任意の数の追加引数を正当に処理する場合、可変長引数の構文が適切なツールです:
<?php
function update_user(int $user_id, string ...$fields): bool {
foreach ($fields as $field) {
// 各フィールドを処理する
}
return true;
}
update_user(42); // 追加引数なし — 問題なし
update_user(42, 'name'); // 追加引数1つ
update_user(42, 'name', 'email'); // 追加引数2つ
修正4:オブジェクトのメソッド呼び出しを確認する
クラスのメソッドも同じエラーをスローします。スタックトレースでクラス名とメソッド名を見つけ、同じ修正を適用します:
<?php
class UserService {
public function update(int $user_id, array $data): bool {
return true;
}
}
$service = new UserService();
// 誤り
$service->update(42);
// Fatal error: Too few arguments to function UserService::update(), 1 passed and exactly 2 expected
// 正しい
$service->update(42, ['name' => 'John']);
呼び出し元の特定
エラーには関数名が表示されますが、どこから呼び出されたかが省略されることがよくあります。例外ハンドラを設定してフルトレースを表示させましょう:
<?php
// エントリファイルの先頭に追加(開発環境のみ)
set_exception_handler(function (Throwable $e) {
echo $e->getMessage() . "\n";
echo $e->getTraceAsString();
});
またはエラーログを直接tail表示します:
tail -f /var/log/php/error.log
# PHP-FPMの場合:
tail -f /var/log/php8.2-fpm.log
どちらの方法でも、問題のある呼び出しの正確なファイルと行番号が得られます:
#0 /var/www/html/controllers/UserController.php(45): update_user(42)
#1 /var/www/html/index.php(12): UserController->save()
PHP 7とPHP 8の動作の違い
このエラーに対するPHPの処理はバージョンをまたいで大幅に厳格化されました。古いコードをアップグレードする際に知っておく価値があります:
- PHP 5.x:引数の不足は
E_WARNINGを発生させました。不足したパラメータは暗黙的にnullに設定されたまま実行が継続されました。 - PHP 7.0以降:
ArgumentCountError(TypeErrorを継承)がスローされます。キャッチされない場合は致命的エラーになります。 - PHP 8.x:7と同じ動作ですが、PHPの組み込み関数も引数不足に対して
ArgumentCountErrorをスローするようになりました。
PHP 5のコードベースを7以降へ移行する場合、長年にわたって静かに壊れていた呼び出しがこのエラーとして表面化することを覚悟してください。
動作確認
修正を加えたら、簡単なサニティチェックを実行します:
# CLIからスクリプトを実行
php -f your_script.php
# または先にlintチェック
php -l your_script.php
LaravelやSymfonyの場合は、最初にクラッシュした該当ルートまたはartisanコマンドを実行してください。ログに致命的エラーが表示されなければ完了です。
予防策
- 厳格な型宣言:ファイルの先頭に
declare(strict_types=1);を追加してください。引数の数のエラーを直接防ぐわけではありませんが、型の規律によって型の不一致を早期に検出できます。 - 静的解析:PHPStanやPsalmはコードが実行される前に引数の数の不一致を検出します:
vendor/bin/phpstan analyse src/ --level=5 - ユニットテスト:正しい引数で関数を呼び出すテストがあれば、誰かがシグネチャを変更した際に即座に検出できます。
- PHPDoc:
@paramブロックで必須パラメータと省略可能なパラメータをドキュメント化してください。IDEがタイピング中に不正な呼び出しを警告してくれます。

