首先我们以添加用户为例来看两个方法:
//方法①
public function addUser(string $userName, string $userPassword, string $telephone, string $userEmail = '')
{
}
//方法②
public function addUser(array $data)
{
}
方法①的优点: 通过方法的定义,就可以清楚的知道方法的参数个数以及数据类型,方便调用者使用。
缺点: 如果参数过多,调用时会非常麻烦,而且如果默认参数有很多,在调用时, 非常容易出错。
方法②的优点: 调用者不需要按照参数的顺序调用,只需要将其拼接成数组即可。
缺点: 调用者必须知道函数内部,究竟需要什么参数,才可以调用,增加了使用难度。
那么,可以通过什么样的方式来使方法②转化为方法①呢?
在之前,我们曾经使用过反射,来调用其他来的方法,那么可不可以通过反射的方式,得到函数的参数顺序和默认值,将方法②中的 $data 转化为 方法①中的参数。
具体实现:
//获取反射类
$className = $this->getReflectionClass($method);
$object = new \ReflectionClass($className);
//获取构造函数
$objectInstance = $object->newInstance();
$reflectionMethod = new \ReflectionMethod($className, $method);
//检测成员方法是否存在
if (empty($reflectionMethod)) {
return '方法不存在';
}
//校验成员方法是否是public
if (!$reflectionMethod->isPublic()) {
return '方法不可用';
}
$parameters = $reflectionMethod->getParameters();//获取所有的参数
if (empty($parameters)) {
//无参数
return $reflectionMethod->invoke($objectInstance);
}
$passParams = [];
foreach ($parameters as $parameter) {
$paramName = $parameter->getName();
if (isset($params[$paramName])) {
//如果参数是数组,必须是数组
if ($parameter->isArray() && !is_array($params[$paramName])) {
return '参数格式错误';
}
$passParams[] = $params[$paramName];
} else if ($parameter->isDefaultValueAvailable()) {
//判断是否有默认值 取参数默认值
$passParams[] = $parameter->getDefaultValue();
} else {
//必填参数 没有填 返回错误
return '参数必填,没传';
}
}
return $reflectionMethod->invoke($objectInstance, ...$passParams);