21
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPのnullの意味

Posted at

PHPでの null と false の使い分けの指針として、タイプヒンティングの仕様を参考に考えるという話。

/**
 * @param \DateTime $d
 * @return \DateTime
 */
function test(\DateTime $d)
{
     return $d;
}

これで DateTime じゃない型の変数を入れると fatal error になる関数のできあがり。

...なんですが、引数を省略できるようにしたいときどうするか。デフォルト引数に意味のあるインスタンスを指定できない(PHPはJavaと違ってstatic領域に静的に存在するインスタンスを定義できない)ので、なにか代わりの即値を入れるんですが...

function test(\DateTime $d = 0) { ... }

これはエラー。

function test(\DateTime $d = false) { ... }

これもエラー。

function test(\DateTime $d = null) { ... }

これはオッケー。タイプヒンティングのある引数のデフォルト引数には null しか書けないのです。

ってことは、これってつまり:

test();

これのことですね。

test(null);

DateTime のインスタンスしかダメなはずの引数なのに、特別に null と書いても通るということ。ここ、0false だと fatal error です。

null でもオッケーな関数宣言をあらためて。

/**
 * @param \DateTime $d
 * @return \DateTime
 */
function test(\DateTime $d=null)
{
     return $d;
}

phpDocの型宣言として見た場合、型の部分は、「その型の値 (もしくは null)」という意味を暗に持つということになります。null instansof Any == true なのです。Javaっぽいです。Scalaで考えるとさらによくわかります。

ということで、戻り値も、その型もしくは null を返すことを保証する、というふうに考えれば、

test(test(null));

は、型違反ではありません。あの「失敗した場合falseを返します」仕様は、このようなタイプヒンティング仕様とは矛盾するのです。というわけで、

/**
 * @param DateTime|false $d
 * @return DateTime|false
 */
function test($d=false) { ... }

こういうのは、せっかくタイプヒンティングのあるPHP5世代のインターフェースとしては、避けたほうがいいですね。false を使う関数は、型を合わせる意識がなかった、あのPHP4時代の名残なのです。

暗黙的に 「null かもしれない」は偏在しているので、false とは違い、Docコメントに @param \DateTime|null $d と書く必要はありません。PhpStormでも、オブジェクトまたは false を入れる関数に関しては、|false が必要ですが、そのいっぽうで |null は書かなくてもそう解釈してくれます。

あ、けど、デフォルト引数指定しないタイプヒンティングは null すら禁止になるので、そこはJavaと違ってていいですね。少なくともあのヌルポの心配はしなくていい。

新しく書くライブラリ、書き換えても問題ない箇所では、積極的に null を使っていきましょうというのが、最近のPHPの仕様変更の理由ですね。これまで書いてた ===false がバグるかもしれないのは辛いですが、まあ、未来に向かっていきますか。

21
21
4

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
21
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?