本文为joshua317原创文章,转载请注明:转载自joshua317博客 https://www.joshua317.com/article/46
自PHP5版本后,PHP具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。
它是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。
其应用场景如:
自动加载插件;
自动生成文档;
依赖注入;
对象池;
动态调用对象的方法,对象方法参数的检测等;
用来扩充PHP语言。
PHP反射API由若干类组成,可帮助我们用来访问程序的元数据或者同相关的注释交互。借助反射我们可以获取诸如类实现了那些方法,创建一个类的实例(不同于用new创建),调用一个方法(也不同于常规调用),传递参数,动态调用类的静态方法。 反射API是PHP内建的OOP技术扩展,包括一些类,异常和接口,综合使用他们可用来帮助我们分析其它类,接口,方法,属性,方法和扩展。这些OOP扩展被称为反射。
我们用的比较多的是 ReflectionClass类、ReflectionObject 和ReflectionMethod类,
ReflectionClass 通过类名获取类的信息;
ReflectionObject 通过类的对象获取类的信息;
ReflectionMethod 获取一个方法的有关信息。
其他的还有
ReflectionException类
ReflectionFunction类
ReflectionExtension类
ReflectionFunctionAbstract 类
ReflectionGenerator类
ReflectionParameter 类
ReflectionProperty类
ReflectionType类
User类
<?php
class User
{
/**
* 性别常量,1代表男,2代表女
*/
const USER_GENDER_1 = 1;
const USER_GENDER_2 = 2;
/**
* 创建静态私有的变量保存该类对象
*/
private static $instance;
/**
* 用户全局唯一id
*
* @var string
*/
protected $globalId;
/**
* 用户姓名
*
* @var string
*/
protected $name;
/**
* 用户性别,1男;2女
*
* @var int
*/
protected $gender;
/**
* 用户手机号
*
* @var string
*/
protected $mobile;
/**
* @return string
*/
public function getGlobalId(): string
{
return $this->globalId;
}
/**
* @param string $globalId
*/
public function setGlobalId(string $globalId): void
{
$this->globalId = $globalId;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @param string $name
*/
public function setName(string $name): void
{
$this->name = $name;
}
/**
* @return int
*/
public function getGender(): int
{
return $this->gender;
}
/**
* @param int $gender
*/
public function setGender(int $gender): void
{
$this->gender = $gender;
}
/**
* @return string
*/
public function getMobile(): string
{
return $this->mobile;
}
/**
* @param string $mobile
*/
public function setMobile(string $mobile): void
{
$this->mobile = $mobile;
}
/**
* 获取用户的单例实现
* @return User
*/
public static function getInstance()
{
//判断实例有无创建,没有的话创建实例并返回,有的话直接返回
if (!(self::$instance instanceof self)) {
self::$instance = new self();
}
return self::$instance;
}
}
PHP
Copy
$className = "User";
$class = new ReflectionClass($className); // 建立User类的反射类
$instance = $class->newInstanceArgs(); // 相当于实例化User类
var_dump($class);
var_dump($instance);
$properties = $class->getProperties();
var_dump($properties);
foreach ($properties as $property) {
echo $property->getName() . "\n";
}
$private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE);
var_dump($private_properties);
foreach ($properties as $property) {
if ($property->isProtected()) {
$docblock = $property->getDocComment();
echo $docblock."\n";
}
}
$methods = $class->getMethods();
var_dump($methods);
$isExistMethod = $class->hasMethod("setMobile");
var_dump($isExistMethod);
$isExistMethod = $class->hasMethod("test");
var_dump($isExistMethod);
$method = $class->getMethod("setMobile");
var_dump($method);
//设置用户姓名
$method = $class->getmethod('setName');// 获取User类中的setName方法
$method->invokeArgs($instance, ["joshua317"]);
//获取用户姓名
$method = $class->getmethod('getName');// 获取User类中的getName方法
$userName = $method->invoke($instance);//执行getName 方法
var_dump($userName);
$method = new ReflectionMethod('User', 'setName');
if ($method->isPublic() && !$method->isStatic()) {
echo "function is protected";
}
// 参数个数
echo $method->getNumberOfParameters();
// 参数对象数组
$params = $method->getParameters();
var_dump($params);
//执行方法
$method->invokeArgs($instance, ["joshua"]);
//获取用户姓名
$method = $class->getmethod('getName');// 获取User类中的getName方法
$userName = $method->invoke($instance);//执行getName 方法
var_dump($userName);
PHP
Copy
1.常量 Contants 2.属性 Property Names 3.方法 Method Names静态 4.属性 Static Properties 5.命名空间 Namespace 6.User类是否为final或者abstract 7.User类是否有某个方法
接下来反射它,只要把类名"User"传递给ReflectionClass就可以了:
$class = new ReflectionClass('User'); // 建立User这个类的反射类
$instance = $class->newInstanceArgs(); // 相当于实例化User类
var_dump($class);
var_dump($instance);
PHP
Copy
#结果如下:
object(ReflectionClass)#1 (1) {
["name"]=>
string(4) "User"
}
object(User)#2 (4) {
["globalId":protected]=>
NULL
["name":protected]=>
NULL
["gender":protected]=>
NULL
["mobile":protected]=>
NULL
}
$properties = $class->getProperties();
var_dump($properties);
foreach ($properties as $property) {
echo $property->getName() . "\n";
}
//结果如下:
array(5) {
[0]=>
object(ReflectionProperty)#3 (2) {
["name"]=>
string(8) "instance"
["class"]=>
string(4) "User"
}
[1]=>
object(ReflectionProperty)#4 (2) {
["name"]=>
string(8) "globalId"
["class"]=>
string(4) "User"
}
[2]=>
object(ReflectionProperty)#5 (2) {
["name"]=>
string(4) "name"
["class"]=>
string(4) "User"
}
[3]=>
object(ReflectionProperty)#6 (2) {
["name"]=>
string(6) "gender"
["class"]=>
string(4) "User"
}
[4]=>
object(ReflectionProperty)#7 (2) {
["name"]=>
string(6) "mobile"
["class"]=>
string(4) "User"
}
}
instance
globalId
name
gender
mobile
PHP
Copy
默认情况下,ReflectionClass会获取到所有的属性,private 和 protected的也可以。如果只想获取到private属性,就要额外传个参数:
$private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE);
var_dump($private_properties);
//结果如下:
array(1) {
[0]=>
object(ReflectionProperty)#8 (2) {
["name"]=>
string(8) "instance"
["class"]=>
string(4) "User"
}
}
可用参数列表:
ReflectionProperty::IS_STATIC
ReflectionProperty::IS_PUBLIC
ReflectionProperty::IS_PROTECTED
ReflectionProperty::IS_PRIVATE
PHP
Copy
通过$property->getName()可以得到属性名。
通过getDocComment可以得到写给property的注释。
foreach ($properties as $property) {
if ($property->isProtected()) {
$docblock = $property->getDocComment();
echo $docblock."\n";
}
}
结果如下:
/**
* 用户全局唯一id
*
* @var string
*/
/**
* 用户姓名
*
* @var string
*/
/**
* 用户性别,1男;2女
*
* @var int
*/
/**
* 用户手机号
*
* @var string
*/
PHP
Copy
getMethods() 来获取到类的所有methods。
hasMethod(string) 是否存在某个方法
getMethod(string) 获取方法
PHP
Copy
$methods = $class->getMethods();
var_dump($methods);
//结果如下:
array(9) {
[0]=>
object(ReflectionMethod)#9 (2) {
["name"]=>
string(11) "getGlobalId"
["class"]=>
string(4) "User"
}
[1]=>
object(ReflectionMethod)#10 (2) {
["name"]=>
string(11) "setGlobalId"
["class"]=>
string(4) "User"
}
[2]=>
object(ReflectionMethod)#11 (2) {
["name"]=>
string(7) "getName"
["class"]=>
string(4) "User"
}
[3]=>
object(ReflectionMethod)#12 (2) {
["name"]=>
string(7) "setName"
["class"]=>
string(4) "User"
}
[4]=>
object(ReflectionMethod)#13 (2) {
["name"]=>
string(9) "getGender"
["class"]=>
string(4) "User"
}
[5]=>
object(ReflectionMethod)#14 (2) {
["name"]=>
string(9) "setGender"
["class"]=>
string(4) "User"
}
[6]=>
object(ReflectionMethod)#15 (2) {
["name"]=>
string(9) "getMobile"
["class"]=>
string(4) "User"
}
[7]=>
object(ReflectionMethod)#16 (2) {
["name"]=>
string(9) "setMobile"
["class"]=>
string(4) "User"
}
[8]=>
object(ReflectionMethod)#17 (2) {
["name"]=>
string(11) "getInstance"
["class"]=>
string(4) "User"
}
}
PHP
Copy
$isExistMethod = $class->hasMethod("setMobile");
var_dump($isExistMethod);
$isExistMethod = $class->hasMethod("test");
var_dump($isExistMethod);
//结果如下:
bool(true)
bool(false)
PHP
Copy
$method = $class->getMethod("setMobile");
var_dump($method);
//结果如下:
object(ReflectionMethod)#18 (2) {
["name"]=>
string(9) "setMobile"
["class"]=>
string(4) "User"
}
PHP
Copy
//设置用户姓名
$method = $class->getmethod('setName');// 获取User类中的setName方法
$method->invokeArgs($instance, ["joshua317"]);
//获取用户姓名
$method = $class->getmethod('getName');// 获取User类中的getName方法
$userName = $method->invoke($instance);//执行getName 方法
var_dump($userName);
//结果如下:
joshua317
PHP
Copy
1.是否"public"、"protected"、"private" 、"static"类型 2.方法的参数列表 3.方法的参数个数 4.反调用类的方法
// 获取方法修饰类型
$method = new ReflectionMethod('User', 'getName');
if ($method->isPublic() && !$method->isStatic()) {
echo "function is public";
}
// 参数个数
echo $method->getNumberOfParameters();
// 参数对象数组
$params = $method->getParameters();
var_dump($params);
//执行方法
$method->invokeArgs($instance, ["joshua"]);
//获取用户姓名
$method = $class->getmethod('getName');// 获取User类中的getName方法
$userName = $method->invoke($instance);//执行getName 方法
var_dump($userName);
//结果如下:
function is public
1
array(1) {
[0]=>
object(ReflectionParameter)#18 (1) {
["name"]=>
string(4) "name"
}
joshua
PHP
Copy
本文为joshua317原创文章,转载请注明:转载自joshua317博客 https://www.joshua317.com/article/46