From ca30385f971c6011f98c972d37ed305043cc3a67 Mon Sep 17 00:00:00 2001 From: Michael Schiemer Date: Mon, 3 Nov 2025 21:45:58 +0100 Subject: [PATCH] refactor(di): remove debug logging from dependency analyzers - Eliminate debug logging clutter in `CyclicDependencyException` and `InitializerDependencyAnalyzer` for cleaner production code. - Simplify and streamline logic by removing unnecessary logs and redundant error tracing. --- .../Exceptions/CyclicDependencyException.php | 18 ---- .../DI/InitializerDependencyAnalyzer.php | 89 +++++++------------ 2 files changed, 30 insertions(+), 77 deletions(-) diff --git a/src/Framework/DI/Exceptions/CyclicDependencyException.php b/src/Framework/DI/Exceptions/CyclicDependencyException.php index a3770a9d..a43878dc 100644 --- a/src/Framework/DI/Exceptions/CyclicDependencyException.php +++ b/src/Framework/DI/Exceptions/CyclicDependencyException.php @@ -262,40 +262,22 @@ final class CyclicDependencyException extends ContainerException // Verwende Analyzer aus Exception (wenn verfügbar) $analyzer = $this->dependencyAnalyzer ?? new InitializerDependencyAnalyzer(); - // DEBUG: Logge welche Dependencies geprüft werden - error_log(sprintf( - "[CYCLIC_DEBUG] Suche problematische Dependency für Interface '%s' in %d Dependencies: [%s]", - $interface, - count($initializerDependencies), - implode(', ', $initializerDependencies) - )); - // Methode 1: Rekursive Suche - Finde vollständigen Pfad für jede Dependency foreach ($initializerDependencies as $dependency) { // Überspringe Container selbst if ($dependency === Container::class || $dependency === 'App\Framework\DI\Container') { - error_log(sprintf("[CYCLIC_DEBUG] Überspringe Container '%s'", $dependency)); continue; } - error_log(sprintf("[CYCLIC_DEBUG] Prüfe Dependency '%s' auf Pfad zu '%s'", $dependency, $interface)); - $path = $analyzer->findDependencyPathToInterface($dependency, $interface); if ($path !== null && !empty($path)) { - error_log(sprintf( - "[CYCLIC_DEBUG] ✅ Pfad gefunden für '%s': [%s]", - $dependency, - implode(' → ', $path) - )); // Der erste Eintrag im Pfad ist die Dependency, die das Interface benötigt return [ 'problematicDependency' => $dependency, 'confirmationMethod' => 'recursive_analysis', 'fullPath' => $path, ]; - } else { - error_log(sprintf("[CYCLIC_DEBUG] ❌ Kein Pfad gefunden für '%s'", $dependency)); } } diff --git a/src/Framework/DI/InitializerDependencyAnalyzer.php b/src/Framework/DI/InitializerDependencyAnalyzer.php index b56300d8..3b8a1863 100644 --- a/src/Framework/DI/InitializerDependencyAnalyzer.php +++ b/src/Framework/DI/InitializerDependencyAnalyzer.php @@ -247,46 +247,25 @@ final readonly class InitializerDependencyAnalyzer array $currentPath = [], int $depth = 0 ): ?array { - // DEBUG: Temporäres Logging - error_log(sprintf( - "[DEPENDENCY_DEBUG] Tiefe %d: Suche Pfad von '%s' zu '%s' (aktueller Pfad: [%s])", - $depth, - $dependencyClass, - $targetInterface, - implode(' → ', $currentPath) - )); - // Max. Rekursionstiefe erreicht if ($depth >= self::MAX_RECURSION_DEPTH) { - error_log(sprintf("[DEPENDENCY_DEBUG] Max. Tiefe erreicht für '%s'", $dependencyClass)); return null; } // Cycle-Detection: Vermeide Endlosschleifen if (in_array($dependencyClass, $visited, true)) { - error_log(sprintf("[DEPENDENCY_DEBUG] Cycle erkannt für '%s' (bereits besucht)", $dependencyClass)); return null; } // Prüfe ob diese Klasse direkt das Interface benötigt if ($this->dependencyNeedsInterface($dependencyClass, $targetInterface)) { - $path = array_merge($currentPath, [$dependencyClass, $targetInterface]); - error_log(sprintf("[DEPENDENCY_DEBUG] ✅ Pfad gefunden: [%s]", implode(' → ', $path))); - return $path; + return array_merge($currentPath, [$dependencyClass, $targetInterface]); } // Rekursiv: Analysiere Dependencies dieser Klasse $dependencies = $this->getClassDependencies($dependencyClass); - error_log(sprintf( - "[DEPENDENCY_DEBUG] '%s' hat %d Dependencies: [%s]", - $dependencyClass, - count($dependencies), - implode(', ', $dependencies) - )); - if (empty($dependencies)) { - error_log(sprintf("[DEPENDENCY_DEBUG] Keine Dependencies für '%s'", $dependencyClass)); return null; } @@ -296,16 +275,9 @@ final readonly class InitializerDependencyAnalyzer foreach ($dependencies as $subDependency) { // Überspringe Container selbst (würde alle Dependencies auflisten) if ($subDependency === Container::class || $subDependency === 'App\Framework\DI\Container') { - error_log(sprintf("[DEPENDENCY_DEBUG] Überspringe Container '%s'", $subDependency)); continue; } - error_log(sprintf( - "[DEPENDENCY_DEBUG] Prüfe Sub-Dependency '%s' (Tiefe %d)", - $subDependency, - $depth + 1 - )); - $path = $this->findDependencyPathToInterface( $subDependency, $targetInterface, @@ -315,12 +287,10 @@ final readonly class InitializerDependencyAnalyzer ); if ($path !== null) { - error_log(sprintf("[DEPENDENCY_DEBUG] ✅ Pfad über '%s' gefunden!", $subDependency)); return $path; } } - error_log(sprintf("[DEPENDENCY_DEBUG] ❌ Kein Pfad gefunden für '%s'", $dependencyClass)); return null; } @@ -394,7 +364,6 @@ final readonly class InitializerDependencyAnalyzer { try { if (!class_exists($className) && !interface_exists($className)) { - error_log(sprintf("[DEPENDENCY_DEBUG] Klasse/Interface existiert nicht: '%s'", $className)); return []; } @@ -402,14 +371,11 @@ final readonly class InitializerDependencyAnalyzer // Wenn es ein Interface ist, versuche die Implementierung zu finden if ($reflection->isInterface()) { - error_log(sprintf("[DEPENDENCY_DEBUG] '%s' ist Interface, suche Implementierung...", $className)); // Suche nach bekannten Implementierungen (basierend auf Namenskonvention) $implClass = $this->findInterfaceImplementation($className); if ($implClass !== null && class_exists($implClass)) { - error_log(sprintf("[DEPENDENCY_DEBUG] ✅ Implementierung gefunden: '%s' → '%s'", $className, $implClass)); $reflection = new \ReflectionClass($implClass); } else { - error_log(sprintf("[DEPENDENCY_DEBUG] ❌ Keine Implementierung für Interface '%s' gefunden", $className)); // Kann keine Dependencies für Interfaces ohne Implementierung finden return []; } @@ -564,50 +530,36 @@ final readonly class InitializerDependencyAnalyzer */ private function findInterfaceImplementation(string $interface): ?string { - error_log(sprintf("[DEPENDENCY_DEBUG] findInterfaceImplementation: Suche Implementierung für '%s'", $interface)); - // 1. Versuche über Container-Bindings (falls Container verfügbar) if ($this->container !== null) { try { - error_log(sprintf("[DEPENDENCY_DEBUG] Container verfügbar, prüfe has('%s')", $interface)); // Prüfe ob Interface gebunden ist if ($this->container->has($interface)) { - error_log(sprintf("[DEPENDENCY_DEBUG] Interface '%s' hat Binding, hole Binding...", $interface)); $binding = $this->getBindingForInterface($interface); if ($binding !== null) { - error_log(sprintf("[DEPENDENCY_DEBUG] Binding gefunden: %s (Typ: %s)", - is_string($binding) ? $binding : (is_object($binding) ? $binding::class : 'callable'), - gettype($binding) - )); - // Wenn Binding ein String ist (Klassenname), verwende diesen if (is_string($binding) && class_exists($binding)) { - error_log(sprintf("[DEPENDENCY_DEBUG] ✅ Verwende String-Binding: '%s'", $binding)); return $binding; } // Wenn Binding ein Objekt ist, verwende dessen Klasse - if (is_object($binding)) { - error_log(sprintf("[DEPENDENCY_DEBUG] ✅ Verwende Objekt-Binding: '%s'", $binding::class)); + // ABER: Überspringe Closure, da wir den Return-Type analysieren müssen + if (is_object($binding) && !($binding instanceof \Closure)) { return $binding::class; } - // Wenn Binding ein Callable ist, können wir es nicht direkt auflösen - // aber wir können versuchen, es zu instanziieren (wenn kein Zyklus) - // Das ist riskant, also überspringen wir es für jetzt - error_log(sprintf("[DEPENDENCY_DEBUG] ⚠️ Binding ist Callable, kann nicht direkt verwendet werden")); - } else { - error_log(sprintf("[DEPENDENCY_DEBUG] ❌ Kein Binding gefunden für '%s'", $interface)); + // Wenn Binding ein Closure ist, versuche Return-Type zu analysieren + if ($binding instanceof \Closure) { + $returnType = $this->getClosureReturnType($binding); + if ($returnType !== null && class_exists($returnType)) { + return $returnType; + } + } } - } else { - error_log(sprintf("[DEPENDENCY_DEBUG] Container->has('%s') = false", $interface)); } - } catch (\Throwable $e) { - error_log(sprintf("[DEPENDENCY_DEBUG] ❌ Container-Zugriff fehlgeschlagen: %s", $e->getMessage())); + } catch (\Throwable) { // Container-Zugriff fehlgeschlagen - ignoriere und versuche Fallback } - } else { - error_log(sprintf("[DEPENDENCY_DEBUG] ❌ Container nicht verfügbar")); } // 2. Versuche Namenskonvention: Interface -> DefaultInterfaceName @@ -654,5 +606,24 @@ final readonly class InitializerDependencyAnalyzer return null; } } + + /** + * Versuche Return-Type eines Closures zu extrahieren + */ + private function getClosureReturnType(\Closure $closure): ?string + { + try { + $reflection = new \ReflectionFunction($closure); + $returnType = $reflection->getReturnType(); + + if ($returnType instanceof \ReflectionNamedType && !$returnType->isBuiltin()) { + return $returnType->getName(); + } + + return null; + } catch (\Throwable) { + return null; + } + } }