/** * 获取invoker信息 * * @param Invoker $invoker * @param $method http方法 * @param $uri http url * @return array */ public function getInvokerInfo($method, $uri, $invoker) { $res = array(); $res['impl'] = $invoker->getMethodName(); $ann = new AnnotationReader(); $refl = new \ReflectionClass($invoker->getClassName()); $mrefl = $refl->getMethod($invoker->getMethodName()); $anns = $ann->getMethodAnnotations($mrefl, true); // 过滤无效的参数 if (isset($anns['param'])) { $anns['param'] = array_values(array_filter($anns['param'], function ($i) { return isset($i['value']); })); } if (isset($anns['return'])) { $anns['return'] = array_values(array_filter($anns['return'], function ($i) { return isset($i['value']); })); } if (isset($anns['throws'])) { $anns['throws'] = array_values(array_filter($anns['throws'], function ($i) { return isset($i['value']); })); } $res['doc'] = $this->getDocText($mrefl->getDocComment()); //找到匹配的@route注释 foreach ($anns['route'] as $route_doc) { //TODO: 同时精确匹配和通配符匹配时, 怎么处理 if (isset($route_doc['value'])) { list($m, $u) = $route_doc['value']; $full_url = $invoker->getContainer()->path . '/' . $u; $full_url = HttpRouterEntries::stringToPath($full_url); if ($full_url == HttpRouterEntries::stringToPath($uri) && $m === $method) { $text = $this->getDocText($route_doc['desc']); if (!empty($text)) { $res['doc'] .= "\r\n"; $res['doc'] .= $text; } break; } } } $anns['route']; $res['root'] = '/'; $res['path'] = $invoker->getContainer()->path; // 获取参数信息 $res['params'] = array(); foreach ($invoker->getParams()->getParams() as $param) { list($is_const, $value, $info, $id) = $param; list($name, $is_ref, $is_optional, $default) = $info; if (!$is_const) { $res['params'][$name] = array('value' => $value, 'is_ref' => $is_ref, 'is_optional' => $is_optional, 'default' => $default, 'doc' => $this->getDocText($anns['param'][$id]['desc'])); } } // 依赖只是特殊的参数 $defaults = $refl->getDefaultProperties(); foreach ($refl->getProperties() as $property) { foreach ($ann->getPropertyAnnotations($property, true) as $type => $value) { if ($type !== 'inject') { continue; } $name = $property->getName(); $value = $value[0]; if (is_array($value['value'])) { $src = $value['value']['src']; if (isset($value['value']['optional']) && $value['value']['optional']) { $is_optional = true; } if (isset($value['value']['default'])) { $default = $value['value']['default']; } } else { $src = $value['value']; } if (substr($src, 0, 1) !== '$') { continue; } if (array_key_exists($name, $defaults)) { $is_optional = true; $default = $defaults[$name]; } $res['params'][$name] = array('value' => $src, 'is_ref' => false, 'is_optional' => $is_optional, 'default' => $default, 'doc' => $this->getDocText($value['desc'])); } } // 获取返回值信息 $res['returns'] = array(); foreach ($invoker->getReturns()->getParams() as $fun_name => $calls) { foreach ($calls as $id => $call) { $args = array(); foreach ($call as $num => $arg) { list($is_const, $value, $pos, $info) = $arg; list($name, $is_ref, $is_optional, $default) = $info; $args[$num] = array('value' => $value, 'name' => $name, 'is_const' => $is_const); } $res['returns'][] = array('name' => $fun_name, 'args' => $args, 'doc' => $id === -1 ? null : $this->getDocText($anns['return'][$id]['desc'])); } } // 获取异常信息 $res['throws'] = array(); foreach ($invoker->getThrows()->getParams() as $exce_name => $throws) { // $res['throws'][$exce_name] = array(); foreach ($throws as $fun_name => $calls) { foreach ($calls as $id => $call) { $args = array(); if ($call !== null) { foreach ($call as $num => $arg) { $args[$num] = array('value' => $arg, 'name' => null, 'is_const' => true); } } $res['throws'][$exce_name][] = array('name' => $fun_name, 'args' => $args, 'doc' => $this->getDocText($anns['throws'][$id]['desc'])); } } } return $res; }