RoutesCommand.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\Devtool\Describe;
  12. use Hyperf\Command\Annotation\Command;
  13. use Hyperf\Command\Command as HyperfCommand;
  14. use Hyperf\Contract\ConfigInterface;
  15. use Hyperf\HttpServer\MiddlewareManager;
  16. use Hyperf\HttpServer\Router\DispatcherFactory;
  17. use Hyperf\HttpServer\Router\Handler;
  18. use Hyperf\HttpServer\Router\RouteCollector;
  19. use Hyperf\Stringable\Str;
  20. use Psr\Container\ContainerInterface;
  21. use Symfony\Component\Console\Helper\Table;
  22. use Symfony\Component\Console\Helper\TableSeparator;
  23. use Symfony\Component\Console\Input\InputOption;
  24. use Symfony\Component\Console\Output\OutputInterface;
  25. #[Command]
  26. class RoutesCommand extends HyperfCommand
  27. {
  28. public function __construct(private ContainerInterface $container, private ConfigInterface $config)
  29. {
  30. parent::__construct('describe:routes');
  31. }
  32. public function handle()
  33. {
  34. $path = $this->input->getOption('path');
  35. $server = $this->input->getOption('server');
  36. $factory = $this->container->get(DispatcherFactory::class);
  37. $router = $factory->getRouter($server);
  38. $this->show(
  39. $this->analyzeRouter($server, $router, $path),
  40. $this->output
  41. );
  42. }
  43. protected function configure()
  44. {
  45. $this->setDescription('Describe the routes information.')
  46. ->addOption('path', 'p', InputOption::VALUE_OPTIONAL, 'Get the detail of the specified route information by path')
  47. ->addOption('server', 'S', InputOption::VALUE_OPTIONAL, 'Which server you want to describe routes.', 'http');
  48. }
  49. protected function analyzeRouter(string $server, RouteCollector $router, ?string $path)
  50. {
  51. $data = [];
  52. [$staticRouters, $variableRouters] = $router->getData();
  53. foreach ($staticRouters as $method => $items) {
  54. foreach ($items as $handler) {
  55. $this->analyzeHandler($data, $server, $method, $path, $handler);
  56. }
  57. }
  58. foreach ($variableRouters as $method => $items) {
  59. foreach ($items as $item) {
  60. if (is_array($item['routeMap'] ?? false)) {
  61. foreach ($item['routeMap'] as $routeMap) {
  62. $this->analyzeHandler($data, $server, $method, $path, $routeMap[0]);
  63. }
  64. }
  65. }
  66. }
  67. return $data;
  68. }
  69. protected function analyzeHandler(array &$data, string $serverName, string $method, ?string $path, Handler $handler)
  70. {
  71. $uri = $handler->route;
  72. if (! is_null($path) && ! Str::contains($uri, $path)) {
  73. return;
  74. }
  75. if (is_array($handler->callback)) {
  76. $action = $handler->callback[0] . '::' . $handler->callback[1];
  77. } elseif (is_string($handler->callback)) {
  78. $action = $handler->callback;
  79. } else {
  80. $action = 'Closure';
  81. }
  82. $unique = "{$serverName}|{$uri}|{$action}";
  83. if (isset($data[$unique])) {
  84. $data[$unique]['method'][] = $method;
  85. } else {
  86. // method,uri,name,action,middleware
  87. $registeredMiddlewares = MiddlewareManager::get($serverName, $uri, $method);
  88. $middlewares = $this->config->get('middlewares.' . $serverName, []);
  89. $middlewares = array_merge($middlewares, $registeredMiddlewares);
  90. $middlewares = MiddlewareManager::sortMiddlewares($middlewares);
  91. $data[$unique] = [
  92. 'server' => $serverName,
  93. 'method' => [$method],
  94. 'uri' => $uri,
  95. 'action' => $action,
  96. 'middleware' => implode(PHP_EOL, $middlewares),
  97. ];
  98. }
  99. }
  100. private function show(array $data, OutputInterface $output)
  101. {
  102. $rows = [];
  103. foreach ($data as $route) {
  104. $route['method'] = implode('|', $route['method']);
  105. $rows[] = $route;
  106. $rows[] = new TableSeparator();
  107. }
  108. $rows = array_slice($rows, 0, count($rows) - 1);
  109. $table = new Table($output);
  110. $table
  111. ->setHeaders(['Server', 'Method', 'URI', 'Action', 'Middleware'])
  112. ->setRows($rows);
  113. $table->render();
  114. }
  115. }