1. <?php
    2. namespace console\component\reflect;
    3. use ReflectionClass;
    4. use Exception;
    5. use ReflectionException;
    6. trait Reflect
    7. {
    8. /**
    9. * 反射调用方法
    10. *
    11. * 示例:
    12. * $clsName = FixOrder::class;
    13. * $funcName = 'receivedNotBuyPicc';
    14. * $parameter = ['order_id' => 123456, 'a' => 222];
    15. * list($code, $ret) = $this->reflectCall($clsName, $funcName, $parameter);
    16. * if ($code === false) {
    17. * throw new Exception($ret);
    18. * }
    19. * @param string $clsName
    20. * @param string $funcName
    21. * @param $parameter
    22. * @return array
    23. */
    24. public function reflectCall(string $clsName, string $funcName, $parameter)
    25. {
    26. try {
    27. // 类
    28. try {
    29. $reflection = new ReflectionClass($clsName);
    30. } catch (ReflectionException $e) {
    31. throw new Exception('类不存在');
    32. }
    33. // 查看是否可以实例化
    34. if (!$reflection->isInstantiable()) {
    35. throw new Exception('类不可实例化');
    36. }
    37. // 构造方法
    38. $constructor = $reflection->getConstructor();
    39. if ($constructor !== null) {
    40. foreach ($constructor->getParameters() as $param) {
    41. if (!$param->isDefaultValueAvailable()) {
    42. throw new Exception('需要处理构造方法');
    43. }
    44. }
    45. }
    46. // 目标方法
    47. try {
    48. $method = $reflection->getMethod($funcName);
    49. } catch (ReflectionException $e) {
    50. throw new Exception('方法不存在');
    51. }
    52. // 方法基本情况
    53. if (!$method->isPublic() || $method->isAbstract()) {
    54. throw new Exception('方法不可调用');
    55. }
    56. // 方法参数
    57. $args = [];
    58. if ($funcParams = $method->getParameters()) {
    59. foreach ($funcParams as $param) {
    60. if (!isset($parameter[$param->name])) {
    61. throw new Exception('缺少参数' . $param->name);
    62. }
    63. $args[] = $parameter[$param->name];
    64. }
    65. }
    66. $cls = $reflection->newInstance();
    67. $ret = $method->invokeArgs($cls, $args);
    68. return [true, $ret];
    69. } catch (Exception $e) {
    70. return [false, $e->getMessage()];
    71. }
    72. }
    73. }