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.
This commit is contained in:
2025-11-03 21:45:58 +01:00
parent f4f367bae4
commit ca30385f97
2 changed files with 30 additions and 77 deletions

View File

@@ -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));
}
}

View File

@@ -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;
}
}
}