diff --git a/app/Services/SidebarMenuService.php b/app/Services/SidebarMenuService.php index ebbb798e..33b693e7 100644 --- a/app/Services/SidebarMenuService.php +++ b/app/Services/SidebarMenuService.php @@ -167,12 +167,18 @@ public function isMenuActive(Menu $menu): bool return $menu->url === $boardMenuUrl; } - // 자식 메뉴가 있는 경우 정확한 URL 매칭만 (하위 경로는 자식 메뉴에서 매칭) - if (isset($menu->menuChildren) && $menu->menuChildren->isNotEmpty()) { - return $currentPath === $menu->url; + // 정확한 URL 매칭 + if ($currentPath === $menu->url) { + return true; } - return $currentPath === $menu->url || str_starts_with($currentPath, $menu->url.'/'); + // prefix 매칭: 다른 메뉴가 현재 URL에 정확히 매칭되면 prefix 매칭 비활성화 + // (예: /esign/create 접속 시, /esign 메뉴가 prefix로 잘못 활성화되는 것 방지) + if (str_starts_with($currentPath, $menu->url.'/')) { + return !self::hasExactMenuMatch($currentPath); + } + + return false; } return false; @@ -233,6 +239,28 @@ private function getBoardMenuUrl(): ?string return $cachedUrl; } + /** + * 현재 URL에 정확히 매칭되는 메뉴가 존재하는지 확인 (캐시) + */ + private static ?bool $exactMatchCache = null; + + private static function hasExactMenuMatch(string $currentPath): bool + { + if (self::$exactMatchCache !== null) { + return self::$exactMatchCache; + } + + $tenantId = auth()->user()?->tenant_id ?? 1; + + self::$exactMatchCache = Menu::withoutGlobalScopes() + ->where('tenant_id', $tenantId) + ->where('is_active', true) + ->where('url', $currentPath) + ->exists(); + + return self::$exactMatchCache; + } + /** * 메뉴 또는 자식 메뉴가 활성 상태인지 확인 */