From f572865b481ec15dca8dd69e26cd634074d6e3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Thu, 12 Feb 2026 12:46:53 +0900 Subject: [PATCH] =?UTF-8?q?fix:=EC=82=AC=EC=9D=B4=EB=93=9C=EB=B0=94=20?= =?UTF-8?q?=EB=A9=94=EB=89=B4=20=EC=A4=91=EB=B3=B5=20=ED=99=9C=EC=84=B1?= =?UTF-8?q?=ED=99=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95=20(v2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 다른 메뉴가 현재 URL에 정확히 매칭될 때 prefix 매칭을 비활성화하여, 형제 메뉴가 동시에 활성화되는 문제 해결. 예: /esign/create 접속 시 /esign 메뉴가 함께 활성화되던 문제. Co-Authored-By: Claude Opus 4.6 --- app/Services/SidebarMenuService.php | 36 +++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) 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; + } + /** * 메뉴 또는 자식 메뉴가 활성 상태인지 확인 */