こんにちは。明月です。
前述でReflectionでクラス<を探してインスタンスを生成する方法、インスタンスの中で変数や関数を探す方法まで説明しました。
link - [PHP] Reflection - Class編
今回はReflectionを利用してクラスで関数を探して実行する方法まで調べてみます。
<?php
class EXClass {
public function test() {
return "test";
}
public function test1() {
return "test1";
}
public function test2() {
return "test2";
}
}
// Query Stringパラメータのparamから値を受取る。
$param = @$_GET["param"];
// ReflectionでEXClassを探す。
$r = new ReflectionClass('EXClass');
// インスタンスを生成する。
$obj = $r->newInstance();
// paramパラメータによってtest関数や、test1関数を呼出す。
$m = $r->getMethod("test".$param);
// 関数を実行する。(パラメータが無いので、初めのパラメータに実行するインスタンスだけ渡す)
$data = $m->invoke($obj);
?>
<!DOCTYPE html>
<html>
<head><title>title</title></head>
<body>
<?=$data?>
</body>
</html>
上の結果をみればQuery Stringのパラメータによって呼出す関数を違うし結果も別で表示されます。
もし、Reflectionがなければ下記とおりに作成したと思います。
$obj = new EXClass();
$data = "";
// Query String paramを受取る。
$param = @$_GET["param"];
// パラメータデータによって呼出す関数を分ける。
if($param == "1") {
$data = $obj->test1();
} else if($param == "2") {
$data = $obj->test2();
} else {
$data = $obj->test();
}
ここでEXClassのクラスの関数が仕様によって増えると考えば「if ~ else」も増えますよ。上の場合は簡単な例なので差をそんなに体感されないですが、拡張的に考えたらもっと複雑なプログラムならすごく複雑なロジックになるでしょう。
Reflection機能でこの関数を動的に呼出すだけではないです。関数がpublicではないアクセス修飾子も呼出すことができます。
<?php
class EXClass {
public function test1() {
return "test";
}
private function test2() {
return "test1";
}
protected function test3() {
return "test2";
}
}
// Reflectionでクラスを探す。
$r = new ReflectionClass('EXClass');
// インスタンスを生成する。
$obj = $r->newInstance();
// インスタンスから「test1」、「test2」、「test3」のメソッドを取得する。
for($i=1; $i <= 3; $i++) {
$m = $r->getMethod("test".$i);
// private、protectedの場合、外部で呼出すができるように設定する。
$m->setAccessible(true);
// 関数をインスタンスから呼出す。
$data[] = $m->invoke($obj);
}
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
<?=$data[0]?><br />
<?=$data[1]?><br />
<?=$data[2]?><br />
</body>
</html>
上の例をみれば「test2」と「test3」関数はpublicではなく、privateやprotectedに設定されています。
そうすると基本的にクラス外部では呼出すことができません。でも、Reflectionの「setAccessible」関数を利用してアクセスができるように設定して呼出しました。
<?php
class EXClass {
public function test($data, $data1, $data2){
return "test";
}
}
$r = new ReflectionClass('EXClass');
$obj = $r->newInstance();
$m = $r->getMethod("test");
// test関数のパラメータ内訳を出力
var_dump($m->getParameters());
?>
<!DOCTYPE html>
<html>
<head><title>title</title></head>
<body></body>
</html>
phpの場合はクラスのメソッドのオーバーロード(同じメソッド名にパラメータのタイプと個数で関数を区別すること)がありません。
それで特にReflectionでメソッドを検索する時にパラメータのタイプや個数の情報はいらないです。Invoke関数を呼び出す時にパラメータの数が一致しないとエラーが発生するため、パラメータの検証が必要になる場合があります。
phpの場合は別に変数の型がないので、変数名と個数で検証処理をすれば良いと思います。
link - https://www.php.net/manual/en/class.reflectionmethod.php
- [CakePHP] RequestとResponseに関して2020/02/12 03:00:02
- [CakePHP] PHPのCakeからAjax要請がある時、jsonタイプ(json_encode関数)でResponseする方法とControllerでViewを選択する方法2020/02/08 03:00:00
- [CakePHP] MVCフレームワークのCakeをインストールする方法2020/02/07 03:00:02
- [PHP] 自動require及びincludeをする方法(spl_autoload_register)2020/02/05 03:00:00
- [PHP] 匿名関数(ラムダ式)とクロージャ(closure)2020/02/04 03:00:00
- [PHP] PHPのコーディング領域とデザイン領域を分離するテンプレートライブラリ Smarty2020/02/02 03:00:00
- [PHP] Reflection - Variable編2020/02/01 03:00:00
- [PHP] Reflection - Method編2020/01/31 03:00:00
- [PHP] Reflection - Class編2020/01/30 03:00:00
- [PHP] エラーページ処理方法(追加: ob_cleanとdie関数使用方法)2020/01/29 03:00:00
- [PHP] 分散設定ファイル(.htaccess) 使用方法2020/01/28 03:00:00
- [PHP] データベース(mariaDB)を連結して使う方法2020/01/24 03:00:00
- [PHP] IOに関して2020/01/23 03:00:00
- [PHP] requireとinclude、そして「@」の使用方法2020/01/22 03:00:00
- [PHP] Fatal及びNotice,、Warningメッセージ処理する方法2020/01/19 03:00:00
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07