4.8 KiB
4.8 KiB
Erweiterungsmuster im Framework
Übersicht
Dieses Dokument beschreibt die verschiedenen Muster und Techniken, um das Framework zu erweitern oder anzupassen, ohne den Kern-Code zu verändern.
Event-basierte Erweiterungen
Event-Listener
Die primäre Methode zur Erweiterung des Frameworks ist das Lauschen auf System-Events:
// Event-Listener registrieren
public function __construct(private readonly EventDispatcher $eventDispatcher)
{
$this->eventDispatcher->addHandler(
'App\Framework\Core\Events\ApplicationBooted',
[$this, 'onApplicationBooted']
);
}
// Event-Handler-Methode
public function onApplicationBooted(ApplicationBooted $event): void
{
// Erweiterungslogik implementieren
}
Eigene Events
Benutzerdefinierte Events erstellen:
final readonly class UserRegistered
{
public function __construct(
public string $userId,
public string $email,
public \DateTimeImmutable $timestamp
) {}
}
// Event auslösen
$this->eventDispatcher->dispatch(new UserRegistered(
$user->getId(),
$user->getEmail(),
new \DateTimeImmutable()
));
Middleware
HTTP-Anfragen können durch Middleware-Klassen erweitert werden:
final readonly class CustomMiddleware implements Middleware
{
public function process(Request $request, callable $next): Response
{
// Vor der Anfrageverarbeitung
$modifiedRequest = $this->modifyRequest($request);
// Anfrage weiterleiten
$response = $next($modifiedRequest);
// Nach der Anfrageverarbeitung
return $this->modifyResponse($response);
}
}
// Middleware registrieren
$app->addMiddleware(CustomMiddleware::class);
Service-Erweiterungen
Service-Ersetzen
Standardimplementierungen durch eigene ersetzen:
#[Initializer]
final readonly class CustomStorageInitializer
{
public function __invoke(Container $container): StorageInterface
{
return new CustomStorage();
}
}
Service-Decorator
Bestehende Services erweitern ohne Änderung der Original-Implementierung:
#[Initializer]
final readonly class LoggingAnalyticsInitializer
{
public function __construct(
private readonly Configuration $config,
private readonly LoggerInterface $logger
) {}
public function __invoke(Container $container): Analytics
{
// Original-Analytics-Service erstellen
$originalAnalytics = new Analytics(
new AnalyticsManager($this->config->get('analytics'), new FileStorage($path)),
$container->get(EventDispatcher::class)
);
// Mit Logging-Decorator umhüllen
return new LoggingAnalyticsDecorator($originalAnalytics, $this->logger);
}
}
// Decorator-Implementierung
final readonly class LoggingAnalyticsDecorator implements AnalyticsInterface
{
public function __construct(
private Analytics $analytics,
private LoggerInterface $logger
) {}
public function track(string $event, array $properties = [], ?string $userId = null): void
{
$this->logger->debug("Tracking event: {$event}", [
'properties' => $properties,
'user_id' => $userId
]);
$this->analytics->track($event, $properties, $userId);
}
// Andere Methoden implementieren
}
Plugin-System
Plugin-Interface
interface PluginInterface
{
public function register(Application $app): void;
public function boot(Application $app): void;
}
// Plugin-Implementierung
final readonly class CustomPlugin implements PluginInterface
{
public function register(Application $app): void
{
// Services registrieren
}
public function boot(Application $app): void
{
// Nach Initialisierung der Anwendung
}
}
// Plugin registrieren
$app->registerPlugin(new CustomPlugin());
Konfigurationserweiterungen
Konfigurationsquellen
Benutzerdefinierte Konfigurationsquellen implementieren:
final readonly class EnvironmentConfigSource implements ConfigSourceInterface
{
public function load(string $key, mixed $default = null): mixed
{
$envKey = strtoupper(str_replace('.', '_', $key));
return $_ENV[$envKey] ?? $default;
}
}
// Konfigurationsquelle registrieren
$config->addSource(new EnvironmentConfigSource());
Zusammenfassung
Die bevorzugten Erweiterungsmuster sind:
- Event-Listener für reaktive Erweiterungen
- Middleware für HTTP-Anfrageverarbeitung
- Service-Initializer zum Ersetzen oder Dekorieren von Services
- Plugins für umfassendere Funktionalitätserweiterungen
- Konfigurationsquellen für benutzerdefinierte Konfigurationen
Diese Muster ermöglichen es, das Framework zu erweitern, ohne den Kern zu modifizieren, was zu einer besseren Wartbarkeit und einfacheren Updates führt.