Code Fix

中級

declare(strict_types=1) で型の異なる引数を渡すと TypeError になる

ファイルの先頭でdeclare(strict_types=1)を宣言すると、関数の型宣言と異なる型の値を渡した際に自動変換されず、TypeErrorになります。strict_typesが無い場合は自動的に型変換されて実行が続きます。

エラーメッセージの読み方

Fatal error: Uncaught TypeError: add(): Argument #2 ($b) must be of type int, string given, called in main.php on line 6 and defined in main.php:3
main.php
ファイル名
3
行番号 — 実際にクラッシュした行
TypeError
例外クラス — 何が起きたか。ここを検索するのが最短です
add(): Argument #2 ($b) must be of type int, string given, called in main.php on line 6 and defined
内容 — どの値が問題だったか

このエラーが出る典型パターン

パターン1

 1  <?php
 2  declare(strict_types=1);
 3  function add(int $a, int $b): int {
 4      return $a + $b;
 5  }
 6  echo add(1, "2"  );
                  ^
Fatal error: Uncaught TypeError: add(): Argument #2 ($b) must be of type int, string given, called in main.php on line 6 and defined in main.php:3

strict_types=1を宣言したファイルでは、int型の引数に文字列を渡しても自動変換されずTypeErrorになります。数値そのものを渡す必要があります。

直し方: "2" を 2 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  <?php
 2  declare(strict_types=1);
 3  function double(float $n): float {
 4      return $n * 2;
 5  }
 6  echo double("3.5" );
                   ^
Fatal error: Uncaught TypeError: double(): Argument #1 ($n) must be of type float, string given, called in main.php on line 6 and defined in main.php:3

strict_typesが有効な状態でfloat型の引数に文字列を渡すとTypeErrorです。数値リテラルとして渡す必要があります。

直し方: "3.5" を 3.5 にします。

この問題を解いてみる →

パターン3

 1  <?php
 2  declare(strict_types=1);
 3  function repeat(string $s, int $times): string {
 4      return str_repeat($s, $times);
 5  }
 6  echo repeat("ab", "3"    );
                         ^
Fatal error: Uncaught TypeError: repeat(): Argument #2 ($times) must be of type int, string given, called in main.php on line 6 and defined in main.php:3

int型の引数に文字列"3"を渡すと、strict_types下では自動変換されずTypeErrorになります。

直し方: "3" を 3 にします。

この問題を解いてみる →

パターン4

 1  <?php
 2  declare(strict_types=1);
 3  function multiply(int $a, int $b): int {
 4      return $a * $b;
 5  }
 6  echo multiply(4, "5"   );
                        ^
Fatal error: Uncaught TypeError: multiply(): Argument #2 ($b) must be of type int, string given, called in main.php on line 6 and defined in main.php:3

strict_types=1の下では、int型の引数に文字列を渡しても自動変換されずTypeErrorになります。

直し方: "5" を 5 にします。

この問題を解いてみる →

パターン5

 1  <?php
 2  declare(strict_types=1);
 3  function greetName(string $n): string {
 4      return "Hi " . $n;
 5  }
 6  echo greetName(5   );
                     ^
Fatal error: Uncaught TypeError: greetName(): Argument #1 ($n) must be of type string, int given, called in main.php on line 6 and defined in main.php:3

strict_types下ではstring型の引数に数値を渡してもTypeErrorになります。

直し方: 5 を "Al" にします。

この問題を解いてみる →

よくある誤解

「PHPは型に緩い言語だから、int型の引数に文字列を渡しても自動変換されるはず」という思い込みは、strict_typesを宣言したファイルには当てはまりません。宣言した瞬間からそのファイル内の型チェックは厳格になります。

実務での勘所

strict_typesの効果は、宣言したファイルの中から関数を呼び出すときの引数の渡し方に対して働きます。呼ばれる側の関数がどのファイルで定義されているか(strict_typesを宣言しているかどうか)は関係ありません。つまり、strict_typesを宣言した自分のファイルから、宣言していない外部ライブラリの関数を呼び出しても、型の変換をしないという厳格な挙動は維持されます。「効果は呼び出し元のファイル単位で決まる」という理解が、strict_typesの正確な仕組みです。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)