タイトルのとおりです。
<?php
function add(int $a, int $b): int
{
return $a + $b;
}
echo add(1, 2.2) . "\n"; // 3
echo add(1, "2") . "\n"; // 3
echo add(1, "1e1") . "\n"; // 11
add(1, "two"); // Fatal error: Uncaught TypeError: add(): Argument #2 ($b) must be of type int, string given
<?php
function not(bool $b): bool
{
return !$b;
}
var_dump(not(0)); // true
var_dump(not("")); // true
not(null); // Fatal error: Uncaught TypeError: not(): Argument #1 ($b) must be of type bool, null given
値の型そのものを見ているわけではなく、値の内容が目的の型に変換できるかどうかが判断基準になっていて、受け入れられると型変換されます。
Web の入力バリデーションで「数字だけで構成されるから数値としてOK」と判断された文字列は、値の型が int にならず文字列のままでも心配ありません。実質 int の string は int 引数の関数に渡せます。DB で integer 型とわかっているものなら、PHP に渡ってくるとき値の型が文字列でも int 引数の関数に安心して渡せます。
PHP は強い型の値を持ちながら、意図的に弱い型のような振る舞いさせる言語です。文字列 IO と親密な関係にあるため、そういう設計方針が適しています。
<?php
function number(...$args): int
{
return implode('', $args);
}
var_dump(number('1', '2', '3')); // int(123)
number('4', 'five');
// PHP8: Fatal error
// PHP7: Notice
戻り値の型チェックもなかなかダイナミックです。型そのものではなく、値の内容がじっさいに変換できるかどうかが問われることがよくわかる例ですね。
変数だけを見て型がわからないので、コンパイル時型推論でガチガチにする言語と PHP の型とはコンセプトがまったく異なる概念だと意識すると、もっと PHP と仲良くできそうです。