🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 反射 反射API功能很强大,甚至能还原这个类的原型,包括方法的访问权限 ~~~ <?php class Person { public $gender; public $name; public function __get($param) { } public function __set($key, $value) { } public function say() { } } //反射获取类的原型 $obj = new ReflectionClass('Person'); $className = $obj->getName(); $methods = $Properties = []; foreach ($obj->getProperties() as $key => $value) { $Properties[$value->getName()]=$value; } foreach ($obj->getMethods() as $key => $value) { $Methods[$value->getName()] = $value; } echo "Class {$className}".PHP_EOL."{".PHP_EOL; is_array($Properties) && ksort($Properties); foreach ($Properties as $key => $value) { echo PHP_EOL; echo $value->isPublic()? 'public':'',$value->isPrivate()?'private':'', $value->isProtected()?'protected':'', $value->isStatic()?'static':''; echo PHP_EOL,$key,PHP_EOL; } echo PHP_EOL; if (is_array($Methods)) ksort($Methods); foreach ($Methods as $key => $value) { echo PHP_EOL,"function {$key} () {}",PHP_EOL; } echo '}',PHP_EOL; ~~~ # 动态代理 ~~~ <?php class mysql { public function connect ($db) { echo "连接到数据库 ${db[0]}",PHP_EOL; } } class sqlproxy { //保存连接数据库 private $target; public function __construct($tar) { //把连接数据库的保存到这里 $this->target[] = new $tar; } public function __call($name, $args) { //使用魔术方法动态代理不需要实现和目标对象一样的方法 //因为自己这个__call就代表所有方法(除静态的) foreach($this->target as $obj) { $r = new ReflectionClass($obj); if($method = $r->getMethod($name)) { if($method->isPublic() && !$method->isAbstract()) { //可以在前置和后置做一些你自定义的事情 echo '方法前置拦截记录---log',PHP_EOL; //可以调用你原来mysql类的方法 $method->invoke($obj, $args); echo '方法后置拦截记录---log',PHP_EOL; } } } } } $obj = new sqlproxy('mysql'); $obj->connect('member'); ~~~ 反射能保持代码的简洁,但是他违背了封装性 php有token函数,可以通过这一机制实现一些反射功能 注意这边的count函数,php7.2有变化注意 ~~~ <?php $tokens = token_get_all('<?php echo(123);'); // print_r($tokens);die; for($i=0; $i < count($tokens); $i++){ for($j=1; $j < count($tokens[$i]); $j++){ echo PHP_EOL; //token_name可以将数字表示的字符串的类型转化为php中固定名称,此函数PHP自带 $token_name = token_name($tokens[$i][0]); echo $token_name; echo PHP_EOL; //把预定义的字符转换为 HTML 实体 echo htmlspecialchars($tokens[$i][$j]); } } $tokens = token_get_all('<?php echo(123); ?>'); for($i=0 ; $i<count($tokens);$i++){ for($j=0 ; $j<count($tokens[$i]);$j++){ echo PHP_EOL; echo htmlspecialchars($tokens[$i][$j]); } } ~~~