menuId) { $fail(__('validation.not_self_parent')); return; } // 이동하려는 메뉴의 모든 자손 ID를 수집 $descendantIds = $this->collectDescendantIds($this->menuId); // 새 부모가 자손에 포함되면 순환 참조 if (in_array((int) $value, $descendantIds, true)) { $fail(__('validation.not_circular_parent')); } } /** * 특정 메뉴의 모든 자손 ID를 재귀적으로 수집합니다. * * @param int $menuId 대상 메뉴 ID * @return array 자손 메뉴 ID 목록 */ private function collectDescendantIds(int $menuId): array { $descendants = []; $childIds = Menu::where('parent_id', $menuId)->pluck('id')->toArray(); foreach ($childIds as $childId) { $descendants[] = $childId; $descendants = array_merge($descendants, $this->collectDescendantIds($childId)); } return $descendants; } }