PHPのリフレクション機能といえば大昔から真面目に実装されている割にはドキュメントが一切ないことで有名です(例:ReflectionFunctionAbstract::getExtensionName())。見りゃわかるでしょ的な機能も多いんですが、とはいえ久々に見るとウッとなるので皆さん少しずつでもメモを残せばいいと思います。
拡張モジュール名と関数名を取り出す
さて、早速ですがmail()
関数とstrlen()
関数の拡張モジュール名と関数名を取り出してみましょう。
<?php
$refl_methods = [
'getExtensionName',
'getName',
];
$target_func =[
'mail',
'strlen',
];
foreach ($target_func as $func) {
$refl = new \ReflectionFunction($func);
$ret = [];
foreach ($refl_methods as $method) {
$ret[$method] = $refl->$method();
}
var_dump($ret);
}
これを実行すると以下の結果を得ます。
$ php /tmp/reflection-test.php
array(2) {
["getExtensionName"]=>
string(8) "standard"
["getName"]=>
string(4) "mail"
}
array(2) {
["getExtensionName"]=>
string(4) "Core"
["getName"]=>
string(6) "strlen"
}
最初の配列から、mail()
関数はstandard拡張モジュールに属していることがわかります。つまり、mail()
の実装を調べたかったらPHPソースコードのext/standard/
以下を探せばいいわけです(普通はそんなことせずに全体をgrep
すると思いますが)。
一方、strlen()
の拡張モジュール名は「Core」だそうです。そういえばphpinfo()
にもCoreって書いてありますけど、今まで気にしたことがありませんでしたね。他の拡張モジュールと異なり、この実体はZend/zend_builtin_functions.c
にあります。
mbstring.func_overload
を有効にしてみる
さて、上のコードをmbstring.func_overload
を有効にして再度実行してみましょう。mbstring.func_overload
はPHPの一部の組み込み関数をmbstringの提供する関数に置き換えてしまうというPHPのオシャレ機能で、PHP 7.2で非推奨に格下げにしようかどうか議論をしているというステータスです。
$ php -dmbstring.func_overload=3 /tmp/reflection-test.php
array(2) {
["getExtensionName"]=>
string(8) "mbstring"
["getName"]=>
string(12) "mb_send_mail"
}
array(2) {
["getExtensionName"]=>
string(8) "mbstring"
["getName"]=>
string(9) "mb_strlen"
}
mbstring.func_overload
で関数が置き換えられた結果、どちらの関数もmbstring拡張モジュールに所属していることがわかります。また、getName()
メソッドの返す値は実体の関数名mb_***()
になっています。少し面白いですね。