我因为要使用 动态加载对象,而不是调用静态方法,所以我改造了一下,官方肯定也能做到,但是或许有别的考虑所有没有上线这种办法,想问问官方为啥不让他调用动态对象呢?
如果不喜欢,请联系我删除。。
改造1:
$statistic_address = 'udp://127.0.0.1:55656';
// 判断数据是否正确
if(empty($data['class']) || empty($data['method']) || !isset($data['param_array']))
{
// 发送数据给客户端,请求包错误
return $connection->send(array('code'=>400, 'msg'=>'bad request', 'data'=>null));
}
// 获得要调用的类、方法、及参数
$class = $data['class'];
//获取实例化对象的时候构造函数所要携带的参数
$class_param= $data['class_param']??null;
$method = $data['method'];
$param_array = $data['param_array'];
StatisticClient::tick($class, $method);
$success = false;
// 判断类对应文件是否载入
//注册自动加载对象机制
spl_autoload_register(function ($class)use ($method,$statistic_address,$connection){
//根据 Folder1.NameSpace.Class1 解析,加载/Services/Folder1/NameSpace/Class1.php
$disk_path=__DIR__.'/Services/'.str_replace('\\','/',$class).'.php';
//如果文件不存在
if(!is_file($disk_path)){
$code=500;
$msg='文件不存在'.$disk_path;
StatisticClient::report($class, $method, false, $code, $msg, $statistic_address);
// 发送数据给客户端 类不存在
return $connection->send(['code'=>$code, 'msg'=>$msg, 'data'=>null]);
}
//这里只能加载一次,否则出现重复定义
require_once $disk_path;
});
$class_=explode('.',$class);
$class_name=array_pop($class_);//获取到对象名
$class_namespace=implode('\\',$class_);//获取对象命名空间
$obj=$class_namespace.'\\'.$class_name;// Folder1\NameSpace\Class1();
try{
//获取反射对象
$con=new ReflectionClass($obj);
//利用反射机制加载,并且传入非限定数量参数 __construct($arg1,$arg2...)
$new=$con->newInstanceArgs($class_param);
//调用 对象的method方法,并且动态传入非限定数量参数$param_array
$ret=call_user_func_array([$new,$method],$param_array);
//释放变量
unset($new);
}catch (Exception $e){
//捕捉到异常
$code = $e->getCode() ? $e->getCode() : 500;
StatisticClient::report($class, $method, $success, $code, $e, $statistic_address);
if(strpos($e->getMessage(),'not exist')!==false){
$msg='捕捉到异常:加载文件成功!但是实例化对象'.$obj.'失败,请注意命名空间';
}else{
$msg='捕捉到异常:加载文件成功!实例化对象成功!执行出错'.$e->getMessage();
}
return $connection->send(['code'=>$code, 'msg'=>$msg, 'data'=>$e]);
}catch (Error $e){
//捕捉到错误
$code = $e->getCode() ? $e->getCode() : 500;
$msg='捕捉到错误'.$e->getMessage();
return $connection->send(['code'=>$code, 'msg'=>$msg, 'data'=>$e]);
}
return $connection->send(['code'=>0, 'msg'=>'ok', 'data'=>$ret]);
/**
* 获取一个实例
* @param string $service_name
* @return instance of RpcClient
*/
public static function instance($service_name,array $serviceParam=[])
{
if(!isset(self::$instances[$service_name]))
{
self::$instances[$service_name] = new self($service_name,$serviceParam);
}
return self::$instances[$service_name];
}
/**
* 构造函数
* @param string $service_name
*/
protected function __construct($service_name,$serviceParam)
{
$this->serviceParam=$serviceParam;
$this->serviceName = $service_name;
}
// 配置服务端列表
RpcClient::config($address_array);
// qq.qrlogin对应 /JsonRpc/Services/qq/qrlogin.php 中的qrlogin类
//第二个参数填写 __construct($arg1,$arg2=[],$arg3) 但是不能传入 资源类对象
$user_client = RpcClient::instance('qq.qrlogin',['arg1','arg2'=>[],'arg3'=>123]);
$a=$user_client->getqrpic('1','22',[]);
静态方法性能好一些,没有其它考虑。
有很多用户改造成了非静态调用,没有问题。