例1:リフレクションを利用した簡単なアプリケーション
本稿のサンプルアプリケーションのテストには、リスト1に示すTestClassクラスを使用しました。このクラスのコードは本稿の冒頭のリンクからダウンロードできます。
<?php /** * Test function (no arguments) */ function testFunction_1(){ return 'You just called the function testFunction_1...'; } /** * Test function (two arguments) */ function testFunction_2($arg1,$arg2){ return 'You just called the function testFunction_2...'; } /** * Test interface (1) */ interface TestInterface_1 { } /** * Test interface (2) */ interface TestInterface_2 { } /** * Test superclass */ class SuperTestClass{ function __construct() {} } /** * Test class for Reflection API */ class TestClass extends SuperTestClass implements TestInterface_1, TestInterface_2 { public static $testProperty_1 = "testProperty_1"; protected $testProperty_2 = "testProperty_2"; private $testProperty_3 = "testProperty_3"; const testConstant_1 = "testConstant_1"; const testConstant_2 = "testConstant_2"; const testConstant_3 = "testConstant_3"; /** * The TestClass constructor */ function __construct() { } /** * testMethod_1 (no arguments) */ function testMethod_1(){ return 'You just called the public method testMethod_1...'; } /** * testMethod_2 (two arguments) */ function testMethod_2($arg_1, $arg_2){ return "You just called the public method testMethod_2 with " + "two arguments: arg_1 = ".$arg_1." , arg_2=".$arg_2; } /** * static testMethod_3 (no arguments) */ static function testMethod_3(){ return "You just called the static method testMethod_3..."; } /** * static testMethod_4 (two arguments) */ static function testMethod_4($arg_1, $arg_2){ return "You just called the static method testMethod_4 with " + "two arguments: arg_1 = ".$arg_1." , arg_2=".$arg_2; } } ?>
以降では、前節で示したリフレクションAPIの情報を使用して開発した、簡単な通貨換算アプリケーションの例を紹介します。処理の出発点は「index.htm」というHTMLページです(図2)。このページ自体には特別変わった点はありません。

HTMLは次のとおりです。
<html> <head> <h3>Currency converter</h3> </head> <body> <form method="get" action="currencyconverter.php"> <b>Convert this amount:<br /><br /></b> <input type="text" value="1" name="amount"> <br /><br /> <hr> <b> From this currency:</b><b> To this currency </b> <br /><br /> <select name="currency1" size="1"> <option value="EUR">EUR <option value="USD">USD <option value="GBP">GBP</select> <select name="currency2" size="1"> <option value="EUR">EUR <option value="USD">USD <option value="GBP">GBP</select> <hr> <input type="submit" value="Exchange"> <input type="reset" value="Reset"> </form> </body> </html>
肝心なのは、ユーザーが値を入力し、換算元と換算先の通貨を選択してからの処理です。換算元と換算先を示すドロップダウンリストには、3種類の通貨を示す略語が表示されています。米ドルを表す「USD」、英ポンドを表す「GBP」、ユーロを表す「EUR」です。ユーザーが[Exchange]ボタンをクリックすると、フォームからデータが送信され、CurrencyConverterという名前のPHPクラスインスタンスがサーバーによって作成されます。このクラスには、起こり得る6種類の換算のそれぞれに対応した6種類のメソッドが備わっています。
<?php class CurrencyConverter { function __construct() {} function EUR_USD($eur) { $usd=1.38745*$eur; return $eur.' EUR = '.$usd.' USD '; } function USD_EUR($usd) { $eur=0.7274*$usd; return $usd.' USD = '.$eur.' EUR '; } function GBP_EUR($gbp) { $eur=1.44610*$gbp; return $gbp.' GBP = '.$eur.' EUR '; } function EUR_GBP($eur) { $gbp=0.69151*$eur; return $eur.' EUR = '.$gbp.' GBP '; } function GBP_USD($gbp) { $usd=2.00640*$gbp; return $gbp.' GBP = '.$usd.' USD '; } function USD_GBP($usd) { $gbp=0.49840*$usd; return $usd.' USD = '.$gbp.' GBP '; } } ?>
換算に使用するメソッドは、ユーザーが選んだ通貨に応じて変わるので、呼び出すべき適切なメソッドを実行時に判断する必要があります。一連の条件分岐ステートメントで判断したり、call_user_funcメソッドを使用したりという手もありますが、PHP5のリフレクションを使用すれば、もっとエレガントに処理を実現できます。呼び出すメソッドを判断するのは簡単です。CurrencyConverterのメソッドの名前は、EUR_USDやUSD_EURなどの形式になっています。ユーザーが2つの通貨を選択すると、コンソールから、それらの通貨を表す略語が送信されます。PHPのコードでは、送信された2つの通貨の文字列をアンダースコアで連結すればいいのです。たとえば、ユーザーが選んだ換算元がユーロ(EUR)で、換算先がポンド(GBP)の場合、アプリケーションで呼び出すのはEUR_GBPメソッドです。アプリケーションでそのメソッドを実際に呼び出すときには、リフレクションを使用します。以上の一連の処理のコードは「currencyconverter.php」ページにあり、次のようになっています。
<?php //include the CurrencyConverter class include("CurrencyConverter.inc"); //Get the amount to be converted $amount=$_GET['amount']; //From this currency... $currency1=$_GET['currency1']; //To this currency... $currency2=$_GET['currency2']; //Obtain the correct method name $name=$_GET['currency1'].'_'.$_GET['currency2']; //get a ReflectionMethod for the $name method $reflectionMethod=new ReflectionMethod( 'CurrencyConverter', $name); //create an instance of the CurrencyConverter class $currencyConverter=new CurrencyConverter(); //invoke the correct method echo $reflectionMethod->invoke($currencyConverter, $amount); ?>
