招聘网站官网,邵阳竞价网站建设设计,外贸网站的推广方法,公司网站备案PHP中的反射API就像Java中的java.lang.reflect包一样。它由一系列可以分析属性、方法和类的内置类组成。它在某些方面和对象函数相似#xff0c;比如get_class_vars()#xff0c;但是更加灵活#xff0c;而且可以提供更多信息。反射API也可与PHP最新的面向对象特性一起工作比如get_class_vars()但是更加灵活而且可以提供更多信息。反射API也可与PHP最新的面向对象特性一起工作如访问控制、接口和抽象类。旧的类函数则不太容易与这些新特性一起使用。看过框架源码的朋友应该对PHP的反射机制有一定的了解像是依赖注入对象池类加载一些设计模式等等都用到了反射机制。
反射API的部分类
使用反射API这些类可以获得在运行时访问对象、函数和脚本中的扩展的信息。通过这些信息可以用来分析类或者构建框架。
类描 述Reflection为类的摘要信息提供静态函数export()ReflectionClass类信息和工具ReflectionMethod类方法信息和工具ReflectionParameter方法参数信息ReflectionProperty类属性信息ReflectionFunction函数信息和工具ReflectionExtensionPHP扩展信息ReflectionException错误类
获取类的信息
我们在工作中使用过一些用于检查类属性的函数例如get_class_methods、getProduct等。这些方法对获取详细类信息有很大的局限性。
我们可以通过反射API类Reflection 和 ReflectionClass 提供的静态方法 export 来获取类的相关信息 export 可以提供类的几乎所有的信息包括属性和方法的访问控制状态、每个方法需要的参数以及每个方法在脚本文档中的位置。这两个工具类 export 静态方法输出结果是一致的只是使用方式不同。
首先构建一个简单的类
?phpclass 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);
打印结果 ReflectionClass::export() 输出
ReflectionClass类提供了非常多的工具方法官方手册给的列表如下 ReflectionClass
使用 Reflection::export() 获取类信息
$prodClass new ReflectionClass(Student);
Reflection::export($prodClass);
打印结果 Reflection::export() 输出
创建 ReflectionClass对象后就可以使用 Reflection 工具类输出 Student 类的相关信息。Reflection::export() 可以格式化和输出任何实现 Reflector 接口的类的实例。
检查类
前面我们了解的 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
除了获取类的相关信息还可以获取 ReflectionClass 对象提供自定义类所在的文件名及文件中类的起始和终止行等相关源代码信息。
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;}
}(length486)
我们看到 getClassSource 接受一个 ReflectionClass 对象作为它的参数并返回相应类的源代码。该函数忽略了错误处理在实际中应该要检查参数和结果代码
检查方法
类似于检查类ReflectionMethod 对象可以用于检查类中的方法。
获得 ReflectionMethod 对象的方法有两种
第一种是通过 ReflectionClass::getMethods() 获得 ReflectionMethod 对象的数组这种方式的好处是不用提前知道方法名会返回类中所有方法的 ReflectionMethod 对象。
第二种是直接使用 ReflectionMethod 类实例化对象这种方式只能获取一个类方法对象需要提前知道方法名。
ReflectionMethod 对象的工具方法 ReflectionMethod
ReflectionClass::getMethods()
我们可以通过 ReflectionClass::getMethods() 获得 ReflectionMethod 对象的数组。
$prodClass new ReflectionClass(Student);
$methods $prodClass-getMethods();
var_dump($methods);
打印结果
array (size4)0 object(ReflectionMethod)[2]public name string __construct (length11)public class string Student (length7)1 object(ReflectionMethod)[3]public name string setName (length7)public class string Student (length7)2 object(ReflectionMethod)[4]public name string setAge (length6)public class string Student (length7)3 object(ReflectionMethod)[5]public name string setSex (length6)public class string Student (length7)
可以看到我们获取到了 Student 的 ReflectionMethod 对象数组每个元素是一个对象其中有两个公共的属性name 为方法名class 为所属类。我们可以调用对象方法来获取方法的信息。
ReflectionMethod
直接使用 ReflectionMethod 类获取类方法有关信息
$method new ReflectionMethod(Student, setName);
var_dump($method);
打印结果
object(ReflectionMethod)[1]public name string setName (length7)public class string Student (length7)
注意
在PHP5中如果被检查的方法只返回对象即使对象是通过引用赋值或传递的那么 ReflectionMethod::retursReference() 不会返回 true。只有当被检测的方法已经被明确声明返回引用在方法名前面有符号时ReflectionMethod::returnsReference() 才返回 true。
检查方法参数
在PHP5中声明类方法时可以限制参数中对象的类型因此检查方法的参数变得非常必要。
类似于检查方法ReflectionParameter 对象可以用于检查类中的方法该对象可以告诉你参数的名称变量是否可以按引用传递还可以告诉你参数类型提示和方法是否接受空值作为参数。
获得 ReflectionParameter 对象的方法有同样两种这和获取 ReflectionMethod 对象非常类似
第一种是通过 ReflectionMethod::getParameters() 方法返回 ReflectionParameter 对象数组这种方法可以获取到一个方法的全部参数对象。
第二种是直接使用 ReflectionParameter 类实例化获取对象这种方法只能获取到单一参数的对象。
ReflectionParameter 对象的工具方法 ReflectionParameter
ReflectionMethod::getParameters()
同获取方法此方法会返回一个数组包含方法每个参数的 ReflectionParameter 对象
$method new ReflectionMethod(Student, setName);
$params $method-getParameters();
var_dump($params);
打印结果
array (size1)0 object(ReflectionParameter)[2]public name string name (length4)
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 (length1)
我们再定义一个函数测试一下
function foo($a, $b, $c) { }
$reflect new ReflectionParameter(foo, c);
var_dump($reflect);
打印结果
object(ReflectionParameter)[2]public name string c (length1)
结语
php的反射API功能非常的强大它可以将一个类的详细信息获取出来。我们可以通过反射API编写个类来动态调用Module对象该类可以自由加载第三方插件并集成进已有的系统。而不需要把第三方的代码硬编码进原有的代码中。虽然实际开发中使用反射情况比较少但了解反射API对工作中对代码结构的了解和开发业务模式帮助还是非常大的。此篇博文断断续续的写了很久主要就是懒如有错误与不足欢迎指正建议