あなたのファイルの中で、オプションの条件であって もしそれを満たさなくても動作するという条件があったとしましょう。 たとえばこのようなものです。 「if function_exists { 何かをする } else { 別のことをする }」
こんな場合の対応は簡単です。 要求されている関数がオプションであることを指定すればいいのです。
この "errorHandler.php" というコードを動かすのに必要な PHP のバージョンを調べることを考えてみましょう。 標準では、PCI は PHP 4.3.0 と返します (debug_backtrace が使えるのがバージョン 4.3.0 以降だからです)。ここで、最小バージョンを調べる際に debug_backtrace を無視させるようにすれば、 本当の結果が得られます。
<?php // ... if (function_exists('debug_backtrace')) { $backtrace = debug_backtrace(); } else { $backtrace = false; } // ... ?> |
ここでは次のようなシンプルな検出スクリプトを使用します。 2 番目のパラメータで渡したオプション配列に注目しましょう (これがミソです)。
<?php require_once 'PHP/CompatInfo.php'; $source = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'errorHandler.php'; $options = array('ignore_functions' => array('debug_backtrace')); $info = new PHP_CompatInfo(); $info->parseFile($source, $options); // 共通形式のメソッドをつかってもかまいません: $info->parseData($source, $options); ?> |
結果はこのようになります。
array ( 'ignored_files' => array ( ), 'ignored_functions' => array ( 0 => 'debug_backtrace', ), 'ignored_extensions' => array ( ), 'ignored_constants' => array ( ), 'max_version' => '', 'version' => '4.0.0', 'extensions' => array ( ), 'constants' => array ( ), 'tokens' => array ( ), 'cond_code' => array ( 0 => 1, ), ) |
注意 バージョン 1.7.0 以降、このような状況を (より簡単に) 処理できるようになり、function_exists で条件指定されているすべての関数を調査範囲からはずせるようになりました。 次の例を参照ください。
もうひとつの方法として ignore_functions_match オプションを使うこともできます。
<?php require_once 'PHP/CompatInfo.php'; $source = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'errorHandler.php'; $options = array('ignore_functions_match' => array('function_exists', array('/.*/'))); $info = new PHP_CompatInfo(); $info->parseFile($source, $options); // 共通形式のメソッドをつかってもかまいません: $info->parseData($source, $options); ?> |
文字列 function_exists を最初のパラメータで指定することで、php の function_exists() による条件の中でだけ登場する関数は無視させるようにしています。
もうひとつ、preg_match 文字列を使用することもできます。 これはより自由な設定をすることができるもので、 そのパターンにマッチする関数は無視させることができます。
一方、2 番目のパラメータの配列では、無視させるパターン (関数名) の一覧を指定します。
ディレクトリ全体をパースすることは、 それが再帰的であるかどうかにかかわらず、 単一のファイルの PHP バージョンを検出するのと同じようなものです。
次の例では、HTML_CSS 1.5.1 の自動検出を行います。 ご覧のとおり、基本的な検出では正確な結果とはなりません。 しかし、オプションを指定することで正確な結果 (PHP バージョン 4.3.0 以降が必要) が得られます。
まず、アーカイブを http://pear.php.net/package/HTML_CSS/download/1.5.1 からダウンロードしてそれを一時ディレクトリ (今回の例では '/tmp') に展開します。
ここで注目するのは、2 つの重要なファイル CSS.php と CSS/Error.php です。 そこで、PCI に対して examples/ ディレクトリと tests/ ディレクトリは無視するように指示します。
検出用のスクリプトはこのようになります。
<?php require_once 'PHP/CompatInfo.php'; $source = '/tmp/HTML_CSS-1.5.1'; $options = array('ignore_dirs' => array('examples', 'tests')); $info = new PHP_CompatInfo(); $info->parseDir($source, $options); // you may also use unified method: $info->parseData($source, $options); ?> |
そして、表示される結果はこのようになります。
array ( 'ignored_files' => array ( 0 => '/tmp/HTML_CSS-1.5.1/ChangeLog', 1 => '/tmp/HTML_CSS-1.5.1/package.xml', 2 => '/tmp/HTML_CSS-1.5.1/tests/AllTests.php', 3 => '/tmp/HTML_CSS-1.5.1/tests/HTML_CSS_TestSuite_Bugs.php', 4 => '/tmp/HTML_CSS-1.5.1/tests/HTML_CSS_TestSuite_Standard.php', 5 => '/tmp/HTML_CSS-1.5.1/tests/stylesheet.css', 6 => '/tmp/HTML_CSS-1.5.1/examples/CSS_Advanced.php', 7 => '/tmp/HTML_CSS-1.5.1/examples/CSS_DisplayOnline.php', 8 => '/tmp/HTML_CSS-1.5.1/examples/css_errorstack_custom.php', 9 => '/tmp/HTML_CSS-1.5.1/examples/css_errorstack_logger.php', 10 => '/tmp/HTML_CSS-1.5.1/examples/css_error_custom.php', 11 => '/tmp/HTML_CSS-1.5.1/examples/css_error_ignore.php', 12 => '/tmp/HTML_CSS-1.5.1/examples/css_error_logger.php', 13 => '/tmp/HTML_CSS-1.5.1/examples/CSS_grepStyles.php', 14 => '/tmp/HTML_CSS-1.5.1/examples/CSS_InHeader.php', 15 => '/tmp/HTML_CSS-1.5.1/examples/CSS_Inline.php', 16 => '/tmp/HTML_CSS-1.5.1/examples/CSS_Logger.php', 17 => '/tmp/HTML_CSS-1.5.1/examples/CSS_parseData.php', 18 => '/tmp/HTML_CSS-1.5.1/examples/CSS_req12194_atrule_api.php', 19 => '/tmp/HTML_CSS-1.5.1/examples/CSS_req12194_atrule_parser.php', 20 => '/tmp/HTML_CSS-1.5.1/examples/CSS_Stylesheet.php', 21 => '/tmp/HTML_CSS-1.5.1/examples/CSS_validate.php', ), 'ignored_functions' => array ( ), 'ignored_extensions' => array ( ), 'ignored_constants' => array ( ), 'max_version' => '', 'version' => '5.0.0', 'extensions' => array ( 0 => 'date', 1 => 'pcre', ), 'constants' => array ( ), 'tokens' => array ( ), 'cond_code' => array ( 0 => 1, ), '/tmp/HTML_CSS-1.5.1/CSS.php' => array ( 'ignored_functions' => array ( ), 'ignored_extensions' => array ( ), 'ignored_constants' => array ( ), 'max_version' => '', 'version' => '5.0.0', 'extensions' => array ( 0 => 'date', 1 => 'pcre', ), 'constants' => array ( ), 'tokens' => array ( ), 'cond_code' => array ( 0 => 1, ), ), '/tmp/HTML_CSS-1.5.1/CSS/Error.php' => array ( 'ignored_functions' => array ( ), 'ignored_extensions' => array ( ), 'ignored_constants' => array ( ), 'max_version' => '', 'version' => '4.3.0', 'extensions' => array ( 0 => 'date', ), 'constants' => array ( ), 'tokens' => array ( ), 'cond_code' => array ( 0 => 0, ), ), ) |
でも、この結果は間違っています。 HTML_CSS 1.5.1 は PHP 4.3.0 以降で動作するのです。
ティップ cond_code オフセットをゼロ以外の値にすれば、 このバージョンが間違っていることがよくわかることでしょう。
パッケージ PEAR::HTML_CSS 1.5.1 は、条件コードを使用して PHP の過去のバージョンで使用できない関数のエミュレートを行っています。 HTML_CSS では、php の関数 function_exists() を用いてその代替実装を行っているのです。
実際のソースコード (CSS.php) を見てみましょう。
<?php // ... if (function_exists('file_put_contents')) { file_put_contents($filename, $this->toString()); } else { $file = fopen($filename, 'wb'); fwrite($file, $this->toString()); fclose($file); } // ... ?> |
それでは、条件コードをより正確に処理できるようにする方法を見ていきましょう。