LoginSignup
31
25

More than 5 years have passed since last update.

PHP 7.0でnullableな型宣言を使いたい場合の裏技

Posted at

これも小ネタ。

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両方とも)。良くわかりませんね。

31
25
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
25