PHP 5.6で、php 関数function_exists()の奇妙な動作に出くわしました。問題は、関数名パラメーターを文字列として直接提供すると、結果が変数として提供された場合とは異なることです。コードは次のとおりです。
$f='posix_getpwuid';
$r1=function_exists('posix_getpwuid');
$r2=function_exists($f);
echo phpversion() . "\n";
var_dump($r1);
var_dump($r2);
結果は次のとおりです。
5.6.5
bool(true) # $r1=function_exists('posix_getpwuid');
bool(false) # $r2=function_exists($f);
どちらの場合もfalseになるはずです。
さらに深く掘り下げると、OPCacheと関係があることがわかりました。OPCache が無効になっている場合、結果は問題ありません。両方の呼び出しで false が返されます。ただし、OPCache を有効にすると、最初の実行では問題ありませんが、2 回目の実行では (つまり、キャッシュされた結果が提供されると)、結果が正しくありません。
関数posix_getpwuidは、 PHP 構成のdisable_functionsで無効になっています。存在しない関数名でテストすると、正しい結果が得られます。
PHP 5.5.21 でテストすると、結果は問題ありません (OPCache の有無にかかわらず)。
PHP 5.5 と 5.6 の両方で Zend OPcache v7.0.4-dev を使用します。
PHP 開発者にバグを送信することを考えています。何かを見逃していないことを確認したかっただけです。
ありがとう。
編集: 新しくコンパイルされた PHP 5.6.6 および 5.6.7 でもテストされています。OSはCentOS 6.6にフルアップデート。結果は、5.6.6 または 5.6.7 で同じです。
ビルド オプションなしでビルドされた PHP:
./configure \
--prefix=/usr/local/php/5.6.7-test
本当にシンプルなphp.iniで
disable_functions = posix_getpwuid
date.timezone = Europe/Prague
zend_extension=/usr/local/php/5.6.7-test/lib/php/extensions/no-debug-non-zts-20131226/opcache.so
テスト スクリプト:
<?
echo phpversion() . "\n";
$f='posix_getpwuid';
$r1=function_exists('posix_getpwuid');
$r2=function_exists($f);
echo "\n\n";
echo "string: ";
var_dump ($r1);
echo "var. : ";
var_dump ($r2);
echo "opcache status: ";
var_dump(opcache_get_status()['opcache_enabled']);
そして結果 - 最初の実行と正しい結果:
# /usr/local/php/php-TEST/bin/php-cgi -c /data/web/php-test/ fce.php
X-Powered-By: PHP/5.6.7
Content-type: text/html; charset=UTF-8
5.6.7
string: bool(false)
var. : bool(false)
opcache status: bool(true)
2 回目の実行 - OPCache によって提供され、結果が悪い:
# /usr/local/php/php-TEST/bin/php-cgi -c /data/web/php-test/ fce.php
X-Powered-By: PHP/5.6.7
Content-type: text/html; charset=UTF-8
5.6.7
string: bool(true)
var. : bool(false)
opcache status: bool(true)
(理由はよくわかりませんが、php
onlyで実行するとOPCacheが起動しなかったので、使用しましたphp-cgi
)