PHP放射机制和具体应用
PHP的反射机制介绍:
php的反射API功能非常的强大,它可以将一个类的详细信息获取出来,比如:类、方法、属性、参数和注释等,其功能十分强大,经常用于高扩展的PHP框架,自动加载插件,自动生成文档,甚至可以用来扩展PHP语言。由于它是PHP內建的oop扩展,为语言本身自带的特性,所以不需要额外添加扩展或者配置就可以使用。
先说一个项目中用到的具体案例
在微信开发中,微信会将所有的消息全部转发到我们的服务器,我们需要根据不同的消息来处理不同的响应,如果全部写在一个方法中,采用if else 或 switch 来分支判断,将会导致代码的不便于维护性,这样的方式会导致代码是如下形式
常规优化是将每一个分支里面的代码再次封装,这里不再说明 下面我们采用策略者模式来优化过多的分支,可以很好的看到反射在其中扮演的重要角色
- 定义一个抽象类
/**
* 定义一个消息抽象类,也可以用接口类: interface
*
* Class MessageController
* @package App\Http\Controllers\Wx
*/
abstract class MessageController {
abstract function MsgType();
}
- 创建具体的消息类,继承抽象类,并实现MsgType方法
这里创建一个视频消息处理类
VideoMsgController
类名是微信返回的消息类型中的首字母大写+MsgController,同理可将所有的消息类都创建出来,至于为啥这么处理,下文有介绍
/**
* 收到的视频消息处理类
*
* Class VideoMsgController
* @package App\Http\Controllers\Wx
*/
class VideoMsgController extends MessageController {
private $content;
//$content为微信服务器转发过来的具体消息
public function __construct($content) {
$this->content = $content;
}
//实现MsgType方法,这里就是主要的业务逻辑处理
public function MsgType() {
// TODO: Implement MsgType() method.
return $return = [
'MsgType' => 'text', 'Content' => '收到的视频消息处理类',
];
}
}
- 利用反射机制将微信的具体反射到对应的消息类 我们创建一个专门类来处理这个反射机制,便于更好理解
class ContextController {
private $strategy;
//$strategyName 微信的消息类型
//$data 微信的消息实体,他们两个在一个XML格式里面,为了便于理解,我将其拆分出来
public function __construct($strategyName, $data) {
try {
$strategyReflection = new \ReflectionClass('\\' . __NAMESPACE__ . '\\' . ucfirst($strategyName) . 'MsgController');
$this->strategy = $strategyReflection->newInstance($data);
} catch (\ReflectionException $e) {
$this->strategy = new DefaultMsgController();
}
}
public function Message() {
return $this->strategy->MsgType();
}
}
分析:
第8行:采用反射,ReflectionClass 接受一个参数,需要反射的类名,带完整的命名空间,这也就解释了为啥将消息类取名为首字母大写+MsgController
第9行:newInstance 创建一个新的类实例,当类不存在时会抛出一个异常。所以我定义了一个 DefaultMsgController 类
第15行:就是去实现消息类中的MsgType方法
- 优化上文的switch分支
$a = new ContextController($values->MsgType, (array)$values);
$data_msg = $a->Message();
反射机制使用demo
关于反射的使用场景等可以百度,包括但不限于:依赖注入、自动生成文档等 百度找的Demo