CheckMenuRoutes.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Module\System\Models\AdminMenu;
  4. use Illuminate\Console\Command;
  5. use Illuminate\Support\Facades\Route;
  6. use Illuminate\Support\Str;
  7. class CheckMenuRoutes extends Command
  8. {
  9. /**
  10. * The name and signature of the console command.
  11. *
  12. * @var string
  13. */
  14. protected $signature = 'admin:check-menu-routes {--delete : 是否删除无效的菜单项}';
  15. /**
  16. * The console command description.
  17. *
  18. * @var string
  19. */
  20. protected $description = '检查菜单项是否指向有效的路由,特别是那些可能会导致404错误的菜单项';
  21. /**
  22. * 已知的有效路由前缀
  23. *
  24. * @var array
  25. */
  26. protected $validPrefixes = [
  27. 'auth', 'dashboard', 'helpers', 'media', 'settings', 'logs', 'config'
  28. ];
  29. /**
  30. * Execute the console command.
  31. *
  32. * @return int
  33. */
  34. public function handle()
  35. {
  36. $this->info("开始检查菜单项是否指向有效的路由...");
  37. // 获取所有菜单项
  38. $menus = AdminMenu::all();
  39. // 获取所有路由
  40. $routes = Route::getRoutes();
  41. $routeUris = [];
  42. foreach ($routes as $route) {
  43. if (Str::startsWith($route->uri(), 'admin/')) {
  44. $routeUris[] = str_replace('admin/', '', $route->uri());
  45. }
  46. }
  47. $validMenus = [];
  48. $invalidMenus = [];
  49. foreach ($menus as $menu) {
  50. // 跳过空URI的菜单项(父菜单)
  51. if (empty($menu->uri)) {
  52. continue;
  53. }
  54. // 跳过已知有效的路由前缀
  55. $isValidPrefix = false;
  56. foreach ($this->validPrefixes as $prefix) {
  57. if (Str::startsWith($menu->uri, $prefix)) {
  58. $isValidPrefix = true;
  59. break;
  60. }
  61. }
  62. if ($isValidPrefix) {
  63. $validMenus[] = $menu;
  64. continue;
  65. }
  66. // 检查URI是否存在于路由中
  67. $uri = ltrim($menu->uri, '/');
  68. $isValid = false;
  69. foreach ($routeUris as $routeUri) {
  70. if (Str::startsWith($routeUri, $uri) || $routeUri === $uri) {
  71. $isValid = true;
  72. break;
  73. }
  74. }
  75. if ($isValid) {
  76. $validMenus[] = $menu;
  77. } else {
  78. $invalidMenus[] = $menu;
  79. }
  80. }
  81. // 显示有效的菜单项
  82. $this->info("\n有效的菜单项(有对应的路由): " . count($validMenus) . " 个");
  83. // 显示无效的菜单项
  84. if (count($invalidMenus) > 0) {
  85. $this->info("\n无效的菜单项(没有对应的路由): " . count($invalidMenus) . " 个");
  86. $table = [];
  87. foreach ($invalidMenus as $menu) {
  88. $table[] = [
  89. 'id' => $menu->id,
  90. 'title' => $menu->title,
  91. 'uri' => $menu->uri,
  92. 'parent_id' => $menu->parent_id,
  93. 'order' => $menu->order
  94. ];
  95. }
  96. $this->table(['ID', '标题', 'URI', '父ID', '排序'], $table);
  97. // 删除无效的菜单项
  98. if ($this->option('delete') || $this->confirm('是否要删除这些无效的菜单项?')) {
  99. foreach ($invalidMenus as $menu) {
  100. // 获取子菜单
  101. $childMenus = AdminMenu::where('parent_id', $menu->id)->get();
  102. // 更新子菜单的父ID
  103. foreach ($childMenus as $childMenu) {
  104. $childMenu->parent_id = $menu->parent_id;
  105. $childMenu->save();
  106. $this->info(" - 更新子菜单: ID = {$childMenu->id}, 标题 = {$childMenu->title}, 新父ID = {$menu->parent_id}");
  107. }
  108. // 删除菜单项
  109. $menu->delete();
  110. $this->info(" - 删除菜单项: ID = {$menu->id}, 标题 = {$menu->title}, URI = {$menu->uri}");
  111. }
  112. $this->info("\n已删除 " . count($invalidMenus) . " 个无效的菜单项");
  113. }
  114. } else {
  115. $this->info("\n所有菜单项都指向有效的路由!");
  116. }
  117. return 0;
  118. }
  119. }