これも小ネタ。
PHP7.0の重用な新機能として、タイプヒンティングにプリミティブ型(int, string, float, booleanなど)が指定できるようになりました。(スカラー型宣言)
関数・メソッドの引数の型チェックすることは防衛的プログラミングの基本ですから、せっかくPHP 7を使うのであれば積極的に活用していきたいところですね。
しかし、一つ困ったことが。それはnull
を許容できないことです。
PHP7.0でのスカラー型宣言
declare(strict_types=1); // 自動型変換を無効(このファイルのみ)
function test(int $n) // $n は intでなければならない。
{
}
test(1); // OK
test('1'); // NG PHP Fatal error: Uncaught TypeError: Argument 1 passed to test() must be of the type integer, string given
// declare(strict_types=1); の指定がないと暗黙の型変換によって1に変換されてチェックが通ってしまうことに注意。
test(null); // NG Fatal error: Uncaught TypeError: Argument 1 passed to test() must be of the type integer, null given
PHP 7.1であればnullable な型がサポートされているので、型名の前に?
を追加すればOKです。(ちなみにnullableはプリミティブだけではなく、クラス名指定の場合にも付与可能。)
PHP7.1ならnullable可
declare(strict_types=1);
function test(?int $n) // $n は int か null でなければならない。
{
}
test(1); // OK
test('1'); // NG PHP Fatal error: Uncaught TypeError: Argument 1 passed to test() must be of the type integer, string given
test(null); // OK
さて、PHP 7.0で同じことするにはどうしたら良いでしょうか? 実は引数のデフォルト値として=null
を指定するとnull
が許容されるようになります。
PHP7.0でなんちゃってnullable
declare(strict_types=1);
function test(int $n = null) // なんちゃってnullableで、$n は int か null でなければならないようにする。
{
}
test(1); // OK
test('1'); // NG PHP Fatal error: Uncaught TypeError: Argument 1 passed to test() must be of the type integer, string given
test(null); // OK
test(); // OK
PHP 5系のタイプヒンティングでも同様の方法でnullableを指定できてましたので、その流れでしょう。正式な構文なのか、単純にバグなのかちょっと理解に迷うところではあります。
ちなみに、デフォルト引数を使えばint型を宣言していても文字列を指定できるのか? というと…。
デフォルト引数に文字列を渡してみる。
function test(int $n = 'abc') // PHP Fatal error: Default value for parameters with a integer type can only be integer or NULL
{
}
怒られちゃいました(PHP 7.0/7.1両方とも)。良くわかりませんね。