PHPと仲良くなろう − empty()とdefine() −

はじめに

こんにちは、グリーでエンジニアをやっている梶原と申します。
今日は、以前PHPについて気になって調べたことについて、紹介したいと思います。
敬遠されがちなPHPですが、中身を知ると自然と愛着が湧いてきます。

empty()について

empty()と言えば、PHPが誇る7不思議関数のひとつです。

こちらにある通り、どうしてtrueになるのかfalseになるのか不明な点が多い関数です。

empty()が呼ばれる箇所を見てみたいと思います。

  • php-5.3.2/Zend/zend_vm_execute.h

22759行目からemptyの処理になります。
isset()がfalseなものはempty()ではtrueになります。
isset()でtrueなものには、i_zend_is_true()でチェックが行われます。

i_zend_is_true()について

i_zend_is_true()を見てみましょう。

  • php-5.3.2/Zend/zend_execute.h

i_zend_is_true()はzend_execute.hに定義されています。

関数を見てみると、変数の型別にチェックしてるのがわかります。
i_zend_is_true()はempty()では反転して評価されることを踏まえて、
配列の場合、105行目でzend_hash_num_elementsが空であればempty()はtrueになったり、
文字列の場合、97、98行目で文字列の長さが0のときと文字列の長さが1のときでも中身が'0'であればempty()はtrueになったりという実装になっています。

定数の話とTRUE, FALSE, NULLについて

次は定数の話とTRUE, FALSE, NULLがなにものかについてです。

PHP上で使ってみると、

となって、論理型とNULLを定義する定数です。

こちらに書かれている通り定義済みの定数として知られています。

どこで定義されているかを見ていきましょう。
TRUE、FALSE、NULLはzend_constants.cのzend_register_standard_constants()内で定数として定義されています。

  • php-5.3.2/Zend/zend_constants.c

関数の中身を覗いてみると、zend_constantに 123、129、135行目でそれぞれの定数の名前をnameに、 またそれぞれのvalue、typeを入れて zend_register_constant()を通して定数として定義されます。
zend_register_constant()は定数の登録を行う関数です。

define()について

ここでPHP上で定数を定義する際に用いるdefine関数について見てみます。

  • php-5.3.2/Zend/zend_builtin_functions.c

define()でも同じく、zend_register_constant()を通して定数の定義を行っています。 先程と違うところはzend_constant.flagsに大文字小文字を区別するかのフラグがdefine()の引数によりセットできます。 そのため、TRUE, FALSE, NULLは大文字小文字を区別しない定数として定義されています。 そこで大文字小文字を混ぜて、

を実行すると

とすべて同じ値になることがわかります。

zend_register_constant()について

zend_register_constant()で定数が登録される処理を見てみます。

  • php-5.3.2/Zend/zend_constatns.c

zend_constatnt->flagsにCONST_CSがついていないと定数名はzend_str_tolowerを通して小文字に変換されます。
最後にzend_hash_addを使ってzend_constantsに定数が登録されます。

zend_get_constant()について

  • php-5.3.2/Zend/zend_get_constant.c

定数を参照するときはzend_get_constant()が呼ばれてます。
まずは渡された定数名で検索し、ヒットしなければ小文字に変換して再度検索を行ないます。
このときヒットしたものについてはCONST_CSフラグが立っていれば小文字変換後の検索は無効になってます。

さいごに

今回はPHP上での定数の話とempty()について簡単に紹介しました。
次回はarray関数について紹介したいと思います!