# Session Binding Initializer ## Übersicht Der `SessionBindingInitializer` löst das Problem, dass `SessionInterface` während der Bootstrap-Phase noch nicht verfügbar ist, wenn Initializer ausgeführt werden, die `SessionInterface` als Dependency benötigen. ## Problem **Timing-Problem**: `SessionInterface` wird normalerweise von `SessionMiddleware` während der Request-Verarbeitung gebunden. Initializer laufen jedoch während der Bootstrap-Phase, bevor ein Request verarbeitet wird. Dies führt zu Dependency-Injection-Fehlern, wenn Initializer `SessionInterface` als Dependency benötigen. **Beispiel**: `ActionAuthorizationCheckerInitializer` benötigt `SessionInterface`, um `SessionBasedAuthorizationChecker` zu erstellen. Ohne `SessionBindingInitializer` würde die Dependency-Injection fehlschlagen. ## Lösung Der `SessionBindingInitializer` registriert `SessionInterface` als **lazy binding** im Container: ```php #[Initializer] public function __invoke(): void { $sessionManager = $this->sessionManager; $this->container->singleton(SessionInterface::class, function(Container $c) use ($sessionManager) { // Check if Session is already bound (by Middleware) if ($c->has(Session::class)) { return $c->get(Session::class); } // Fallback: Create new session without request context // This will be overridden by SessionMiddleware when request is available return $sessionManager->createNewSession(); }); } ``` ## Funktionsweise 1. **Lazy Binding**: `SessionInterface` wird als Closure registriert, die erst ausgeführt wird, wenn `SessionInterface` tatsächlich benötigt wird. 2. **Fallback-Mechanismus**: - Wenn `SessionMiddleware` bereits gelaufen ist, wird die bereits gebundene `Session` verwendet. - Andernfalls wird eine neue Session ohne Request-Context erstellt. 3. **Override durch Middleware**: `SessionMiddleware` überschreibt das lazy binding mit der tatsächlichen Session-Instanz, wenn ein Request verarbeitet wird. ## Verwendung Initializer, die `SessionInterface` benötigen, können es einfach als Dependency injizieren: ```php final readonly class ActionAuthorizationCheckerInitializer { public function __construct( private Container $container ) { } #[Initializer] public function __invoke(): ActionAuthorizationChecker { // SessionInterface wird automatisch vom lazy binding bereitgestellt $session = $this->container->get(SessionInterface::class); $checker = new SessionBasedAuthorizationChecker($session); $this->container->singleton(ActionAuthorizationChecker::class, $checker); return $checker; } } ``` ## Wichtige Hinweise ### Kein ContextType-Filter **Wichtig**: Der `SessionBindingInitializer` hat **keinen** `ContextType`-Filter: ```php #[Initializer] // ✅ Kein ContextType::WEB Filter public function __invoke(): void ``` **Grund**: Die Discovery läuft während der Bootstrap-Phase, wenn der Context noch `cli-script` ist. Ein `ContextType::WEB` Filter würde dazu führen, dass der Initializer übersprungen wird und `SessionInterface` nicht registriert wird. ### Discovery-Timing Die Discovery scannt Initializer während der Bootstrap-Phase, bevor Requests verarbeitet werden. Initializer mit ContextType-Filtern werden nur ausgeführt, wenn der aktuelle Context passt. Da die Bootstrap-Phase im `cli-script` Context läuft, werden Initializer mit `ContextType::WEB` Filter übersprungen. **Lösung**: Initializer, die für die Dependency-Registrierung benötigt werden, sollten **keinen** ContextType-Filter haben, auch wenn sie nur für WEB-Contexts verwendet werden. ## Dateien - **Initializer**: `src/Framework/Http/Session/SessionBindingInitializer.php` - **Verwendet von**: `src/Framework/LiveComponents/Security/ActionAuthorizationCheckerInitializer.php` - **Middleware**: `src/Framework/Http/Session/SessionMiddleware.php` ## Troubleshooting ### Problem: "Cannot instantiate interface SessionInterface" **Ursache**: `SessionBindingInitializer` wurde nicht gefunden oder nicht ausgeführt. **Lösung**: 1. Prüfe, ob `SessionBindingInitializer` das `#[Initializer]` Attribut hat (ohne ContextType-Filter). 2. Leere den Discovery-Cache: `php console.php discovery:clear-cache` 3. Prüfe die Logs, ob der Initializer gefunden wurde. ### Problem: Initializer wird nicht gefunden **Ursache**: ContextType-Filter verhindert, dass der Initializer während der Bootstrap-Phase gefunden wird. **Lösung**: Entferne den `ContextType`-Filter vom `#[Initializer]` Attribut: ```php // ❌ Falsch: Wird während Bootstrap übersprungen #[Initializer(ContextType::WEB)] // ✅ Richtig: Wird während Bootstrap gefunden #[Initializer] ``` ## Siehe auch - [Dependency Injection](../features/dependency-injection.md) - [Session Management](../features/session-management.md) - [Initializer System](../features/initializer-system.md)