PHP API反射例
9142 ワード
*反射はオブジェクトモデル向けの中元モデルを操作するAPIであり、その機能は非常に強く、複雑で拡張可能なアプリケーションの構築に役立ちます.プラグインの自動ロード、ドキュメントの自動生成、PHP言語の拡張などの用途があります.php反射apiはいくつかのクラスから構成されており、プログラムのメタデータにアクセスしたり、関連する注釈とインタラクティブにしたりするのに役立ちます.反射によってクラスが実現したような方法を得ることができますクラスのインスタンスを作成し(newで作成するのとは異なり)、メソッドを呼び出します.(通常の呼び出しとは異なり)、パラメータの伝達、クラスの動的呼び出しの静的方法.***反射apiは、phpに組み込まれたoop技術の拡張であり、いくつかのクラス、異常、インタフェースを含み、それらを総合的に使用して、他のクラス、インタフェース、方法、属性、方法、拡張を分析するのに役立ちます.これらのoop拡張は、phpソース/ext/reflectionディレクトリの下にある反射と呼ばれます.反射apiで反射api自体を自省する(これは反射の最初の意味かもしれないが、自分が自分を「見る」こと):
ほとんどの反射apiにはreflectorインタフェースが実装されており、このインタフェースを実装するクラスには、パラメータオブジェクトに関する情報を印刷するexportメソッドがあります.get_の使用declared_classes()php内蔵クラスをすべて取得し、get_declared_interfaces();get_defined_functions();get_defined_vars(); get_defined_constants();phpインタフェース、メソッド、変数、定数情報を取得できます.
反射プローブ:
上記のクリップ・インスタンスは、カスタム・クラスの基本情報を表示する方法です.データを記述するデータはメタデータと呼ばれ、反射で取得された情報はメタデータ情報であり、クラス、インタフェースメソッドなどを記述するために使用される.(メタ---は元の意味で、例えばメタモデルはモデルを記述するモデルであり、例えばUMLメタモデルはUML構造を記述するモデルである)、メタデータはさらにハードメタデータ(hard matadata)とソフトメタデータに分けられる(soft metadata)、前者はクラス名、メソッド、パラメータなどのコンパイルコードから導出される.後者はphpDocブロック、phpの属性など、人為的に加わったデータである.
現在、ビジネスソフトウェアの多くは、eclipseやvisual studio、netbeansなどの有名なIDEがプラグインベースのGUIアプリケーションであるプラグインアーキテクチャに基づいています.サードパーティまたは自社がプラグインを開発する場合は、定義された関連インタフェースをインポートして実装する必要があります.最後に実装されたパッケージを指定されたディレクトリの下に配置し、ホストアプリケーションは起動時にすべてのプラグイン実装を自動的に検出し、ロードします.私たち自身がこのようなアーキテクチャを実現したいなら、可能です.
phpにはeclipseのようにプラグインを使用するソリューションもあります.私たちのプラグインを使用します:1.get_を先に使用declared_classes()は、ロードされたすべてのクラスを取得します.2.すべてのクラスを巡り、カスタマイズしたプラグインインタフェースIPluginが実装されているかどうかを判断します.3.すべてのプラグイン実装を取得します.4.ホストアプリケーションでのプラグインとのインタラクション
次の方法は、プラグインインタフェースを実装したすべてのクラスを見つけるのに役立ちます.
すべてのプラグイン実装は、クラス名自体やクラスのインスタンスではなく、反射クラスインスタンスとして返されることに注意してください.反射を使用してメソッドを呼び出すには、いくつかの条件判断が必要だからです.クラスが反射クラスを使用するhasMethod()メソッドを実装しているかどうかを判断します.次に、すべてのプラグインメニュー項目を1つのメニューに配置します.
ここで主に用いられる反射方法の例の方法呼び出し:public mixed invoke(stdclass object,mixed args=null);我々の従来の方法の呼び出しは、$objRef->someMethod($argList...);反射が使用されているため、メソッドを呼び出そうとすると、$reflectionMethodRef->invoke($reflectionClassRef,$argList...)と形式が変わります.反射呼び出しメソッドを使用する場合は、反射メソッドのインスタンスをインスタンス化する必要があります.インスタンスメソッドにインスタンスの参照がある場合は、必要なパラメータを渡す必要があります.静的メソッドが呼び出されるとnullが第1のパラメータとして明示的に入力される.プラグインクラスを実装する他の方法には、同様の処理ロジックがあり、ここでは説明しない.以下は私の簡単なテストです.
****××××$reflectionClass = new ReflectionClass("IPlugIn");echo $reflectionClass-> getDocComment();このコードはクラスのドキュメントコメントを取得するのに役立ちます.クラスのコメントの内容を取得すると、まずコメントを取得し、docblock tokenizer『pecl拡張』を使用したり、独自のTokenizerクラスを使用したり、正規表現、文字列関数を使用してコメントドキュメントを解析したりすることができます.反射呼び出しを使用する前に、注釈によって伝達された命令またはデータを判断する命令を含む、注釈に何でも加えることができます:getDocComment();//analyseは自分で定義したの!!//解析結果に基づいてメソッドを実行したり、パラメータ等if(xxxx){$reflectionMethod->invoke($pluginInstance);}?>注釈は文字列であるため、任意の文字列解析技術を使用して有用な情報を抽出し、これらの情報に基づいて方法を呼び出すことができます.つまり、プログラムの論理は方法によって決定されるだけでなく、注釈によって決定される可能性があります(反射を使用し、注釈フォーマットが厳格に要求されていることを前提としています).
反射apiは他のクラスと同様に拡張を継承できるので、これらのapiに独自の機能を追加することができます.カスタムコメントタグを結合します.@で始まる東、タグ付け(Javaではannotation)、.netでは属性attribute(または特性)と呼ばれます.その後Reflectionクラスを拡張すると、強力な拡張機能を実現できます.特筆すべきは、ファクトリメソッド設計モード(GOFの1つ)です.反射を使用してオブジェクトをインスタンス化することもよくあります.以下は、性質の疑似コードの例です.
<?php
Reflection::export(new ReflectionExtension('reflection'));
?>
ほとんどの反射apiにはreflectorインタフェースが実装されており、このインタフェースを実装するクラスには、パラメータオブジェクトに関する情報を印刷するexportメソッドがあります.get_の使用declared_classes()php内蔵クラスをすべて取得し、get_declared_interfaces();get_defined_functions();get_defined_vars(); get_defined_constants();phpインタフェース、メソッド、変数、定数情報を取得できます.
反射プローブ:
<?php
//
class MyTestClass{
public function testFunc($para0='defaultValue0'){
}
}
//
foreach(get_declared_classes() as $class){
//
$reflectionClass = new ReflectionClass($class);
//
if($reflectionClass->isUserDefined()){
//
Reflection::export($reflectionClass);
}
}
?>
上記のクリップ・インスタンスは、カスタム・クラスの基本情報を表示する方法です.データを記述するデータはメタデータと呼ばれ、反射で取得された情報はメタデータ情報であり、クラス、インタフェースメソッドなどを記述するために使用される.(メタ---は元の意味で、例えばメタモデルはモデルを記述するモデルであり、例えばUMLメタモデルはUML構造を記述するモデルである)、メタデータはさらにハードメタデータ(hard matadata)とソフトメタデータに分けられる(soft metadata)、前者はクラス名、メソッド、パラメータなどのコンパイルコードから導出される.後者はphpDocブロック、phpの属性など、人為的に加わったデータである.
現在、ビジネスソフトウェアの多くは、eclipseやvisual studio、netbeansなどの有名なIDEがプラグインベースのGUIアプリケーションであるプラグインアーキテクチャに基づいています.サードパーティまたは自社がプラグインを開発する場合は、定義された関連インタフェースをインポートして実装する必要があります.最後に実装されたパッケージを指定されたディレクトリの下に配置し、ホストアプリケーションは起動時にすべてのプラグイン実装を自動的に検出し、ロードします.私たち自身がこのようなアーキテクチャを実現したいなら、可能です.
<?php
// UI
interface IPlugin {
//
public static function getName();
//
function getMenuItems();
//
function getArticles();
//
function getSideBars();
}
//
class SomePlugin implements IPlugin {
public function getMenuItems() {
//
return null;
}
public function getArticles() {
//
return null;
}
public function getSideBars() {
//
return array('SideBarItem');
}
//
public static function getName(){
return "SomePlugin";
}
}
?>
phpにはeclipseのようにプラグインを使用するソリューションもあります.私たちのプラグインを使用します:1.get_を先に使用declared_classes()は、ロードされたすべてのクラスを取得します.2.すべてのクラスを巡り、カスタマイズしたプラグインインタフェースIPluginが実装されているかどうかを判断します.3.すべてのプラグイン実装を取得します.4.ホストアプリケーションでのプラグインとのインタラクション
次の方法は、プラグインインタフェースを実装したすべてのクラスを見つけるのに役立ちます.
function findPlugins() {
$plugins = array();
foreach(get_declared_classes() as $class) {
$reflectionClass = new ReflectionClass($class);
// IPlugin
if($reflectionClass->implementsInterface('IPlugin')) {
$plugins[] = $reflectionClass;
}
}
return $plugins;
}
すべてのプラグイン実装は、クラス名自体やクラスのインスタンスではなく、反射クラスインスタンスとして返されることに注意してください.反射を使用してメソッドを呼び出すには、いくつかの条件判断が必要だからです.クラスが反射クラスを使用するhasMethod()メソッドを実装しているかどうかを判断します.次に、すべてのプラグインメニュー項目を1つのメニューに配置します.
function integratePlugInMenus() {
$menu = array();
//
foreach(findPlugins() as $plugin) {
// getMenuItems
if($plugin->hasMethod('getMenuItems')) {
/* ( , , “ ” ), ReflectionMethod */
$reflectionMethod = $plugin->getMethod('getMenuItems');
//
if($reflectionMethod->isStatic()) {
// , null
$items = $reflectionMethod->invoke(null);
} else {
// , 。
$pluginInstance = $plugin->newInstance();
// api ,
$items = $reflectionMethod->invoke($pluginInstance);
}
// 。
$menu = array_merge($menu, $items);
}
}
return $menu;
}
ここで主に用いられる反射方法の例の方法呼び出し:public mixed invoke(stdclass object,mixed args=null);我々の従来の方法の呼び出しは、$objRef->someMethod($argList...);反射が使用されているため、メソッドを呼び出そうとすると、$reflectionMethodRef->invoke($reflectionClassRef,$argList...)と形式が変わります.反射呼び出しメソッドを使用する場合は、反射メソッドのインスタンスをインスタンス化する必要があります.インスタンスメソッドにインスタンスの参照がある場合は、必要なパラメータを渡す必要があります.静的メソッドが呼び出されるとnullが第1のパラメータとして明示的に入力される.プラグインクラスを実装する他の方法には、同様の処理ロジックがあり、ここでは説明しない.以下は私の簡単なテストです.
<?php
/**
*
* */
interface IPlugIn
{
/**
* getSidebars()
*
* @return
*/
public function getSidebars();
/**
* GetName()
*
* @return
*/
public static function GetName();
}
/* , , */
class MyPlugIn implements IPlugIn
{
public function getSidebars()
{
//
$sideBars = '<div><ul >
<li><a href="">m1</a>
</li>
<li><a href="">m2</a>
</li>
</ul>
</div>';
return $sideBars;
}
public static function GetName()
{
return 'MyPlugIn';
}
}
// ;
class MyPlugIn2 implements IPlugIn
{
public function getSidebars()
{
//
$sideBars = '<div><ul >
<li><a href="">mm1</a>
</li>
<li><a href="">mm2</a>
</li>
</ul>
</div>';
return $sideBars;
}
public static function GetName()
{
return 'MyPlugIn2';
}
}
//
class HostApp
{
public function initAll()
{
//
echo "yiqing95.";
$this->renderAll();
}
// GUI
function renderAll(){
$rsltSidebars="<table>";
foreach($this->integrateSidebarsOfPlugin() as $sidebarItem){
$rsltSidebars.="<tr><td>$sidebarItem</td></tr>";
}
$rsltSidebars.="</table>";
echo $rsltSidebars;
}
/* :*/
protected function findPlugins()
{
$plugins = array();
foreach (get_declared_classes() as $class) {
$reflectionClass = new ReflectionClass($class);
if ($reflectionClass->implementsInterface('IPlugin')) {
$plugins[] = $reflectionClass;
}
}
return $plugins;
}
/** ***/
protected function integrateSidebarsOfPlugin()
{
$sidebars = array();
foreach ($this->findPlugins() as $plugin) {
if ($plugin->hasMethod('getSidebars')) {
$reflectionMethod = $plugin->getMethod('getSidebars');
if ($reflectionMethod->isStatic()) {
$items = $reflectionMethod->invoke(null);
} else {
$pluginInstance = $plugin->newInstance();
$items = $reflectionMethod->invoke($pluginInstance) ;
}
}
//$sidebars = array_merge($sidebars, $items);
$sidebars[]=$items;
}
return $sidebars;
}
}
// :
$entryClass =new HostApp();
$entryClass->initAll();
?>
****××××$reflectionClass = new ReflectionClass("IPlugIn");echo $reflectionClass-> getDocComment();このコードはクラスのドキュメントコメントを取得するのに役立ちます.クラスのコメントの内容を取得すると、まずコメントを取得し、docblock tokenizer『pecl拡張』を使用したり、独自のTokenizerクラスを使用したり、正規表現、文字列関数を使用してコメントドキュメントを解析したりすることができます.反射呼び出しを使用する前に、注釈によって伝達された命令またはデータを判断する命令を含む、注釈に何でも加えることができます:getDocComment();//analyseは自分で定義したの!!//解析結果に基づいてメソッドを実行したり、パラメータ等if(xxxx){$reflectionMethod->invoke($pluginInstance);}?>注釈は文字列であるため、任意の文字列解析技術を使用して有用な情報を抽出し、これらの情報に基づいて方法を呼び出すことができます.つまり、プログラムの論理は方法によって決定されるだけでなく、注釈によって決定される可能性があります(反射を使用し、注釈フォーマットが厳格に要求されていることを前提としています).
反射apiは他のクラスと同様に拡張を継承できるので、これらのapiに独自の機能を追加することができます.カスタムコメントタグを結合します.@で始まる東、タグ付け(Javaではannotation)、.netでは属性attribute(または特性)と呼ばれます.その後Reflectionクラスを拡張すると、強力な拡張機能を実現できます.特筆すべきは、ファクトリメソッド設計モード(GOFの1つ)です.反射を使用してオブジェクトをインスタンス化することもよくあります.以下は、性質の疑似コードの例です.
Class XXXFactory{
function getInstance($className){
$reflectionClass =new ReflectionClass($className);
return $reflectionClass->newInstance();
}
// ,
function getInstance(){
$pathOfConfig = "xxx/xx/XXXImplement.php";
$className= Config->getItem($pathOfClass,'SomeClassName');
return $this->getInstance($className);
}
}
:http://blog.csdn.net/siren0203/article/details/5994571