4.9 KiB
Initializer Context Filtering
Übersicht
Initializer können mit ContextType-Filtern versehen werden, um zu steuern, in welchen Execution-Contexts sie ausgeführt werden sollen. Dies ist jedoch mit Vorsicht zu verwenden, da die Discovery während der Bootstrap-Phase läuft.
Problem: Context-Filter während Bootstrap
Wichtig: Die Discovery scannt und verarbeitet Initializer während der Bootstrap-Phase, wenn der Execution-Context noch cli-script ist (nicht web).
Beispiel-Problem
// ❌ Problem: Wird während Bootstrap übersprungen
#[Initializer(ContextType::WEB)]
public function __invoke(): SomeInterface
{
// ...
}
Warum: Die Discovery läuft während der Bootstrap-Phase im cli-script Context. Initializer mit ContextType::WEB Filter werden deshalb übersprungen (shouldSkipInitializer() gibt true zurück).
Lösung: Kein Context-Filter für Dependency-Registrierung
Initializer, die Dependencies registrieren müssen, sollten keinen ContextType-Filter haben:
// ✅ Richtig: Wird während Bootstrap gefunden und ausgeführt
#[Initializer]
public function __invoke(): SomeInterface
{
// ...
}
Wann Context-Filter verwenden?
✅ Geeignet für Context-Filter
- Setup-Initializer (void-Return), die nur in bestimmten Contexts ausgeführt werden sollen
- Initializer, die nur für bestimmte Contexts benötigt werden und keine Dependencies für andere Initializer bereitstellen
❌ Nicht geeignet für Context-Filter
- Initializer, die Interfaces oder Services registrieren, die von anderen Initializern benötigt werden
- Initializer, die während der Bootstrap-Phase verfügbar sein müssen
Beispiel: SessionBindingInitializer
// ✅ Kein Context-Filter: Muss während Bootstrap verfügbar sein
#[Initializer]
public function __invoke(): void
{
// Registriert SessionInterface als lazy binding
// Wird von ActionAuthorizationCheckerInitializer benötigt
}
Grund: SessionBindingInitializer registriert SessionInterface, das von ActionAuthorizationCheckerInitializer benötigt wird. Wenn SessionBindingInitializer einen ContextType::WEB Filter hätte, würde er während der Bootstrap-Phase übersprungen werden, und ActionAuthorizationCheckerInitializer würde fehlschlagen.
Beispiel: ActionAuthorizationCheckerInitializer
// ✅ Kein Context-Filter: Muss während Bootstrap verfügbar sein
#[Initializer]
public function __invoke(): ActionAuthorizationChecker
{
// Benötigt SessionInterface (von SessionBindingInitializer)
// Muss während Bootstrap verfügbar sein, auch wenn nur für WEB verwendet
}
Grund: Obwohl ActionAuthorizationChecker nur für WEB-Requests verwendet wird, muss der Initializer während der Bootstrap-Phase verfügbar sein, damit die Dependency-Injection funktioniert.
Discovery-Prozess
- Bootstrap-Phase: Discovery scannt alle Initializer
- Context-Filter-Prüfung:
shouldSkipInitializer()prüft, ob Initializer für aktuellen Context erlaubt ist - Überspringen: Initializer mit nicht-passendem Context werden übersprungen
- Registrierung: Verbleibende Initializer werden registriert
Best Practices
1. Kein Context-Filter für Dependency-Registrierung
// ✅ Richtig
#[Initializer]
public function __invoke(): SomeInterface
{
// Registriert Interface, das von anderen Initializern benötigt wird
}
2. Context-Filter nur für Setup-Initializer
// ✅ Geeignet: Setup-Initializer mit Context-Filter
#[Initializer(ContextType::WEB)]
public function __invoke(): void
{
// Setup-Code, der nur für WEB-Contexts benötigt wird
// Wird nicht von anderen Initializern benötigt
}
3. Dokumentation hinzufügen
/**
* No ContextType filter: This initializer must be available during bootstrap
* (even if context is cli-script) so it can be registered in the container.
* The actual session will be provided by SessionMiddleware when processing web requests.
*/
#[Initializer]
public function __invoke(): SomeInterface
{
// ...
}
Troubleshooting
Problem: Initializer wird nicht gefunden
Symptom: "No initializers found that return this interface"
Ursache: Initializer hat ContextType-Filter, der während Bootstrap nicht passt
Lösung: Entferne den ContextType-Filter:
// Vorher
#[Initializer(ContextType::WEB)]
// Nachher
#[Initializer]
Problem: Dependency-Injection-Fehler
Symptom: "Cannot resolve parameter 'session' for method..."
Ursache: Initializer, der Dependency bereitstellt, hat ContextType-Filter
Lösung: Entferne den ContextType-Filter vom Dependency-Provider-Initializer