|
クラス情報の取得
作業では、クラス属性をチェックするために、get_class_methods、getProduct などのいくつかの関数を使用しました。これらの方法では、詳細なクラス情報を取得する際に大きな制限があります。
リフレクション API クラス Reflection および ReflectionClass によって提供される静的メソッドのエクスポートを通じて、クラスに関する関連情報を取得できます。エクスポートでは、属性やメソッドのアクセス制御ステータスなど、クラスに関するほぼすべての情報が提供されます。必要なパラメータと、スクリプト ドキュメント内の各メソッドの場所。 これら 2 つのツール クラスは、export static メソッドの出力結果は同じですが、使用方法が異なります。
まず、単純なクラスを構築します
<?php
class Student {
public $name;
protected $age;
private $sex;
public function __construct($name, $age, $sex)
{
$this->setName($name);
$this->setAge($age);
$this->setSex($sex);
}
public function setName($name)
{
$this->name = $name;
}
protected function setAge($age)
{
$this->age = $age;
}
private function setSex($sex)
{
$this->sex = $sex;
}
}
ReflectionClass::export() を使用してクラス情報を取得します
ReflectionClass::export('Student');
印刷結果:
Class [ class Student ] {
@@ D:\wamp\www\test2.php 3-29
- Constants [0] { }
- Static properties [0] { }
- Static methods [0] { }
- Properties [3] {
Property [ public $name ]
Property [ protected $age ]
Property [ private $sex ]
}
- Methods [4] {
Method [ public method __construct ] {
@@ D:\wamp\www\test2.php 8 - 13
- Parameters [3] {
Parameter #0 [ $name ]
Parameter #1 [ $age ]
Parameter #2 [ $sex ]
}
}
Method [ public method setName ] {
@@ D:\wamp\www\test2.php 15 - 18
- Parameters [1] {
Parameter #0 [ $name ]
}
}
Method [ protected method setAge ] {
@@ D:\wamp\www\test2.php 20 - 23
- Parameters [1] {
Parameter #0 [ $age ]
}
}
Method [ private method setSex ] {
@@ D:\wamp\www\test2.php 25 - 28
- Parameters [1] {
Parameter #0 [ $sex ]
}
}
}
}
ReflectionClass クラスには多くのツール メソッドが用意されており、公式マニュアルに記載されているリストは次のとおりです:
ReflectionClass::__construct — 初始化 ReflectionClass 类
ReflectionClass::export — 导出一个类
ReflectionClass::getConstant — 获取定义过的一个常量
ReflectionClass::getConstants — 获取一组常量
ReflectionClass::getConstructor — 获取类的构造函数
ReflectionClass::getDefaultProperties — 获取默认属性
ReflectionClass::getDocComment — 获取文档注释
ReflectionClass::getEndLine — 获取最后一行的行数
ReflectionClass::getExtension — 根据已定义的类获取所在扩展的 ReflectionExtension 对象
ReflectionClass::getExtensionName — 获取定义的类所在的扩展的名称
ReflectionClass::getFileName — 获取定义类的文件名
ReflectionClass::getInterfaceNames — 获取接口(interface)名称
ReflectionClass::getInterfaces — 获取接口
ReflectionClass::getMethod — 获取一个类方法的 ReflectionMethod。
ReflectionClass::getMethods — 获取方法的数组
ReflectionClass::getModifiers — 获取类的修饰符
ReflectionClass::getName — 获取类名
ReflectionClass::getNamespaceName — 获取命名空间的名称
ReflectionClass::getParentClass — 获取父类
ReflectionClass::getProperties — 获取一组属性
ReflectionClass::getProperty — 获取类的一个属性的 ReflectionProperty
ReflectionClass::getReflectionConstant — Gets a ReflectionClassConstant for a class's constant
ReflectionClass::getReflectionConstants — Gets class constants
ReflectionClass::getShortName — 获取短名
ReflectionClass::getStartLine — 获取起始行号
ReflectionClass::getStaticProperties — 获取静态(static)属性
ReflectionClass::getStaticPropertyValue — 获取静态(static)属性的值
ReflectionClass::getTraitAliases — 返回 trait 别名的一个数组
ReflectionClass::getTraitNames — 返回这个类所使用 traits 的名称的数组
ReflectionClass::getTraits — 返回这个类所使用的 traits 数组
ReflectionClass::hasConstant — 检查常量是否已经定义
ReflectionClass::hasMethod — 检查方法是否已定义
ReflectionClass::hasProperty — 检查属性是否已定义
ReflectionClass::implementsInterface — 接口的实现
ReflectionClass::inNamespace — 检查是否位于命名空间中
ReflectionClass::isAbstract — 检查类是否是抽象类(abstract)
ReflectionClass::isAnonymous — 检查类是否是匿名类
ReflectionClass::isCloneable — 返回了一个类是否可复制
ReflectionClass::isFinal — 检查类是否声明为 final
ReflectionClass::isInstance — 检查类的实例
ReflectionClass::isInstantiable — 检查类是否可实例化
ReflectionClass::isInterface — 检查类是否是一个接口(interface)
ReflectionClass::isInternal — 检查类是否由扩展或核心在内部定义
ReflectionClass::isIterateable — 检查是否可迭代(iterateable)
ReflectionClass::isSubclassOf — 检查是否为一个子类
ReflectionClass::isTrait — 返回了是否为一个 trait
ReflectionClass::isUserDefined — 检查是否由用户定义的
ReflectionClass::newInstance — 从指定的参数创建一个新的类实例
ReflectionClass::newInstanceArgs — 从给出的参数创建一个新的类实例。
ReflectionClass::newInstanceWithoutConstructor — 创建一个新的类实例而不调用它的构造函数
ReflectionClass::setStaticPropertyValue — 设置静态属性的值
ReflectionClass::__toString — 返回 ReflectionClass 对象字符串的表示形式。
Use Reflection::クラス情報を取得するには、export() を使用します。
$prodClass = new ReflectionClass('Student');
Reflection::export($prodClass);
結果の印刷
Class [ class Student ] {
@@ D:\wamp\www\test2.php 3-29
- Constants [0] { }
- Static properties [0] { }
- Static methods [0] { }
- Properties [3] {
Property [ public $name ]
Property [ protected $age ]
Property [ private $sex ]
}
- Methods [4] {
Method [ public method __construct ] {
@@ D:\wamp\www\test2.php 8 - 13
- Parameters [3] {
Parameter #0 [ $name ]
Parameter #1 [ $age ]
Parameter #2 [ $sex ]
}
}
Method [ public method setName ] {
@@ D:\wamp\www\test2.php 15 - 18
- Parameters [1] {
Parameter #0 [ $name ]
}
}
Method [ protected method setAge ] {
@@ D:\wamp\www\test2.php 20 - 23
- Parameters [1] {
Parameter #0 [ $age ]
}
}
Method [ private method setSex ] {
@@ D:\wamp\www\test2.php 25 - 28
- Parameters [1] {
Parameter #0 [ $sex ]
}
}
}
}
ReflectionClass オブジェクトを作成した後、Reflection ツール クラスを使用して Student クラスに関する関連情報を出力できます。 。 Reflection::export() は、Reflector インターフェイスを実装する任意のクラスのインスタンスをフォーマットしてエクスポートできます。
Check Class
#ReflectionClass ツール クラスについては以前に学習しましたが、このクラスにはクラス情報を取得するためのツール メソッドが多数提供されていることがわかりました。 。たとえば、Student クラスのタイプと、それがインスタンス化できるかどうかを取得できます。
ツール関数
function classData(ReflectionClass $class) {
$details = '';
$name = $class->getName(); // 返回要检查的类名
if ($class->isUserDefined()) { // 检查类是否由用户定义
$details .= "$name is user defined" . PHP_EOL;
}
if ($class->isInternal()) { // 检查类是否由扩展或核心在内部定义
$details .= "$name is built-in" . PHP_EOL;
}
if ($class->isInterface()) { // 检查类是否是一个接口
$details .= "$name is interface" . PHP_EOL;
}
if ($class->isAbstract()) { // 检查类是否是抽象类
$details .= "$name is an abstract class" . PHP_EOL;
}
if ($class->isFinal()) { // 检查类是否声明为 final
$details .= "$name is a final class" . PHP_EOL;
}
if ($class->isInstantiable()) { // 检查类是否可实例化
$details .= "$name can be instantiated" . PHP_EOL;
} else {
$details .= "$name can not be instantiated" . PHP_EOL;
}
return $details;
}
$prodClass = new ReflectionClass('Student');
print classData($prodClass);
印刷結果
Student is user defined
Student can be instantiated
関連情報を取得することに加えて、このオブジェクトは、カスタム クラスが配置されているファイル名や、ファイル内のクラスの開始行と終了行など、関連するソース コード情報を提供します。
function getClassSource(ReflectionClass $class) {
$path = $class->getFileName(); // 获取类文件的绝对路径
$lines = @file($path); // 获得由文件中所有行组成的数组
$from = $class->getStartLine(); // 提供类的起始行
$to = $class->getEndLine(); // 提供类的终止行
$len = $to - $from + 1;
return implode(array_slice($lines, $from - 1, $len));
}
$prodClass = new ReflectionClass('Student');
var_dump(getClassSource($prodClass));
印刷結果
string 'class Student {
public $name;
protected $age;
private $sex;
public function __construct($name, $age, $sex)
{
$this->setName($name);
$this->setAge($age);
$this->setSex($sex);
}
public function setName($name)
{
$this->name = $name;
}
protected function setAge($age)
{
$this->age = $age;
}
private function setSex($sex)
{
$this->sex = $sex;
}
}
' (length=486)
getClassSource が ReflectionClass オブジェクトをパラメータとして受け取り、対応するクラスのソース コードを返すことがわかります。この関数はエラー処理を無視します。実際には、パラメータと結果コードをチェックする必要があります。
メソッドのチェック
クラスのチェックと同様に、ReflectionMethod オブジェクトを使用してクラス内のメソッドをチェックできます。
ReflectionMethod オブジェクトを取得するには 2 つの方法があります:
1 つ目は、ReflectionClass::getMethods() を通じて ReflectionMethod オブジェクトの配列を取得することです。このメソッドの利点は、メソッド名を事前に知っておくと、クラス内のすべてのメソッドの ReflectionMethod オブジェクトが返されます。
2 つ目の方法は、ReflectionMethod クラスを直接使用してオブジェクトをインスタンス化する方法ですが、この方法では取得できるクラス メソッド オブジェクトは 1 つだけなので、メソッド名を事前に知っておく必要があります。
ReflectionMethod オブジェクトのユーティリティ メソッド:
ReflectionMethod::__construct — ReflectionMethod のコンストラクター
ReflectionMethod::export — コールバック メソッドをエクスポートする
ReflectionMethod::getClosure — 戻り値動的に作成されたメソッド呼び出しインターフェイス 翻訳者注: この戻り値を使用して、非パブリック メソッドを直接呼び出すことができます。
ReflectionMethod::getDeclaringClass — リフレクション関数呼び出しパラメーターのクラス表現を取得します。
ReflectionMethod::getModifiers — メソッドの修飾子を取得します。
ReflectionMethod::getPrototype — メソッドのプロトタイプ (存在する場合) を返します
ReflectionMethod:: invoke — 呼び出し
ReflectionMethod::invokeArgs — パラメーターを使用して実行します
ReflectionMethod::isAbstract — メソッドが抽象メソッドかどうかを判断します
ReflectionMethod::isConstructor — メソッドがコンストラクターであるかどうかを判断します
ReflectionMethod::isDestructor — メソッドがデストラクター メソッドであるかどうかを判断します
ReflectionMethod::isFinal — メソッドが Final として定義されているかどうかを判断します
ReflectionMethod::isPrivate — メソッドがプライベート メソッドであるかどうかを判断します
ReflectionMethod::isProtected — メソッドが保護されたメソッドであるかどうかを判断します (protected )
ReflectionMethod::isPublic — メソッドがパブリック メソッドであるかどうかを判断します
ReflectionMethod::isStatic — メソッドが静的メソッドであるかどうかを判断します
ReflectionMethod::setAccessible — メソッドがアクセス可能かどうかを設定します
ReflectionMethod::__toString — リフレクション メソッド オブジェクトの文字列式を返します
ReflectionClass::getMethods()
ReflectionClass::getMethods() ReflectionMethod オブジェクトの配列を通じて取得できます。
$prodClass = new ReflectionClass('Student');
$methods = $prodClass->getMethods();
var_dump($methods);
印刷結果
array (size=4)
0 => &
object(ReflectionMethod)[2]
public 'name' => string '__construct' (length=11)
public 'class' => string 'Student' (length=7)
1 => &
object(ReflectionMethod)[3]
public 'name' => string 'setName' (length=7)
public 'class' => string 'Student' (length=7)
2 => &
object(ReflectionMethod)[4]
public 'name' => string 'setAge' (length=6)
public 'class' => string 'Student' (length=7)
3 => &
object(ReflectionMethod)[5]
public 'name' => string 'setSex' (length=6)
public 'class' => string 'Student' (length=7)
Student の ReflectionMethod オブジェクト配列を取得したことがわかります。各要素は 2 つのパブリック属性を持つオブジェクトです。name はメソッド名、class は カテゴリです。オブジェクト メソッドを呼び出してメソッド情報を取得できます。
ReflectionMethod
ReflectionMethod クラスを直接使用して、クラス メソッドに関する情報を取得します
$method = new ReflectionMethod('Student', 'setName');
var_dump($method);
結果の印刷
object(ReflectionMethod)[1]
public 'name' => string 'setName' (length=7)
public 'class' => string 'Student' (length=7)
# ## ######知らせ#########在PHP5中,如果被检查的方法只返回对象(即使对象是通过引用赋值或传递的),那么 ReflectionMethod::retursReference() 不会返回 true。只有当被检测的方法已经被明确声明返回引用(在方法名前面有&符号)时,ReflectionMethod::returnsReference() 才返回 true。
检查方法参数
在PHP5中,声明类方法时可以限制参数中对象的类型,因此检查方法的参数变得非常必要。
类似于检查方法,ReflectionParameter 对象可以用于检查类中的方法,该对象可以告诉你参数的名称,变量是否可以按引用传递,还可以告诉你参数类型提示和方法是否接受空值作为参数。
获得 ReflectionParameter 对象的方法有同样两种,这和获取 ReflectionMethod 对象非常类似:
第一种是通过 ReflectionMethod::getParameters() 方法返回 ReflectionParameter 对象数组,这种方法可以获取到一个方法的全部参数对象。
第二种是直接使用 ReflectionParameter 类实例化获取对象,这种方法只能获取到单一参数的对象。
ReflectionParameter 对象的工具方法:
ReflectionParameter::allowsNull — Checks if null is allowed
ReflectionParameter::canBePassedByValue — Returns whether this parameter can be passed by value
ReflectionParameter::__clone — Clone
ReflectionParameter::__construct — Construct
ReflectionParameter::export — Exports
ReflectionParameter::getClass — Get the type hinted class
ReflectionParameter::getDeclaringClass — Gets declaring class
ReflectionParameter::getDeclaringFunction — Gets declaring function
ReflectionParameter::getDefaultValue — Gets default parameter value
ReflectionParameter::getDefaultValueConstantName — Returns the default value's constant name if default value is constant or null
ReflectionParameter::getName — Gets parameter name
ReflectionParameter::getPosition — Gets parameter position
ReflectionParameter::getType — Gets a parameter's type
ReflectionParameter::hasType — Checks if parameter has a type
ReflectionParameter::isArray — Checks if parameter expects an array
ReflectionParameter::isCallable — Returns whether parameter MUST be callable
ReflectionParameter::isDefaultValueAvailable — Checks if a default value is available
ReflectionParameter::isDefaultValueConstant — Returns whether the default value of this parameter is constant
ReflectionParameter::isOptional — Checks if optional
ReflectionParameter::isPassedByReference — Checks if passed by reference
ReflectionParameter::isVariadic — Checks if the parameter is variadic
ReflectionParameter::__toString — To string
ReflectionMethod::getParameters()
同获取方法,此方法会返回一个数组,包含方法每个参数的 ReflectionParameter 对象
$method = new ReflectionMethod('Student', 'setName');
$params = $method->getParameters();
var_dump($params);
打印结果
array (size=1)
0 => &
object(ReflectionParameter)[2]
public 'name' => string 'name' (length=4)
ReflectionParameter
我们来了解一下这种方式,为了更好的理解,我修改一下 Student 类的 setName方法,增加两个参数 a, b
...
public function setName($name, $a, $b)
{
$this->name = $name;
}
...
首先我们看一下 ReflectionParameter 类的构造方法
public ReflectionParameter::__construct ( string $function , string $parameter )
可以看到该类实例化时接收两个参数:
$function:当需要获取函数为公共函数时只需传函数名称即可。当该函数是某个类方法时,需要传递一个数组,格式为:array('class', 'function')。
$parameter:这个参数可以传递两种,第一种为参数名(无$符号),第二种为参数索引。注意:无论是参数名还是索引,该参数都必须存在,否则会报错。
下面举例:
$params = new ReflectionParameter(array('Student', 'setName'), 1);
var_dump($params);
打印结果
object(ReflectionParameter)[1]
public 'name' => string 'a' (length=1)
我们再定义一个函数测试一下
function foo($a, $b, $c) { }
$reflect = new ReflectionParameter('foo', 'c');
var_dump($reflect);
打印结果
object(ReflectionParameter)[2]
public 'name' => string 'c' (length=1)
结语
php的反射API功能非常的强大,它可以将一个类的详细信息获取出来。我们可以通过反射API编写个类来动态调用Module对象,该类可以自由加载第三方插件并集成进已有的系统。而不需要把第三方的代码硬编码进原有的代码中。虽然实际开发中使用反射情况比较少,但了解反射API对工作中对代码结构的了解和开发业务模式帮助还是非常大的。此篇博文断断续续的写了很久(主要就是懒!),如有错误与不足欢迎指正,建议!!
相关教程推荐:《PHP教程》