Action triggers en event listeners
In het kort
Sectie met titel “In het kort”NextPDF verstuurt lifecycle-events via het met PHP Standards Recommendation 14 (PSR-14) compatibele systeem in NextPDF\Event. Registreer een listener, kies een prioriteit en reageer wanneer een document wordt aangemaakt, een pagina wordt toegevoegd, een lettertype wordt geladen, ondertekening of versleuteling wordt uitgevoerd, bytes worden weggeschreven of de uitvoer begint. Stop de keten alleen wanneer dat nodig is.
Installatie
Sectie met titel “Installatie”composer require nextpdf/core:^3Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”Het event-systeem heeft twee publieke onderdelen. ListenerProvider koppelt elke event-klasse aan een gesorteerde lijst met listener-callables. EventDispatcher loopt die lijst af en roept elke listener aan op volgorde van prioriteit. Omdat beide klassen final zijn, gebeurt uitbreiding via compositie en niet via subclassing.
Beide klassen voldoen via duck typing aan PSR-14. EventDispatcher::dispatch() volgt de PSR-14-signatuur van dispatch() en geeft het event terug nadat elke listener is uitgevoerd. ListenerProvider::getListenersForEvent() volgt de PSR-14-provider-signatuur. NextPDF vereist het PSR-14-pakket niet. Ook wanneer uw project dat pakket installeert, blijven de interfaces op elkaar aansluiten.
Voor extensie-auteurs zijn vooral twee gedragingen van belang:
- Wildcard-luisteren. Om listeners te resolven, doorloopt de provider de bovenliggende klassen en interfaces van het event. Koppel een listener aan de basisklasse
AbstractEventom elk lifecycle-event te volgen. Koppel er een aan een interface om een eventfamilie af te vangen. - Prioriteit en propagatie. Bij een hogere prioriteit wordt de listener eerder uitgevoerd. Gelijke prioriteiten behouden de registratievolgorde. Elk event dat
AbstractEventuitbreidt, is stopbaar. Een listener kanstopPropagation()aanroepen; daarna slaat de dispatcher de rest over.
De dispatcher heeft een snelpad zonder overhead. Wanneer er voor een event-klasse of bovenliggende klasse geen listener is gekoppeld, keert dispatch() na één controle met hasListeners() direct terug.
Lifecycle-events
Sectie met titel “Lifecycle-events”| Event | Namespace | Geactiveerd wanneer | Stabiliteit |
|---|---|---|---|
DocumentCreatedEvent | NextPDF\Event\Document | Documentconstructie is voltooid | experimental |
PageAddedEvent | NextPDF\Event\Document | Een pagina is volledig geïnitialiseerd | experimental |
ContentRenderedEvent | NextPDF\Event\Content | Inhoud wordt naar een pagina gerenderd | experimental |
FontLoadedEvent | NextPDF\Event\Content | Een lettertypefamilie en -stijl worden voor het eerst geladen | experimental |
SignatureAppliedEvent | NextPDF\Event\Security | Handtekeningbytes worden ingebed | experimental |
EncryptionAppliedEvent | NextPDF\Event\Security | Versleuteling wordt geconfigureerd | experimental |
PdfSerializedEvent | NextPDF\Event\Writer | Serialisatie is voltooid | experimental |
DocumentOutputEvent | NextPDF\Event\Document | Uitvoerlevering staat op het punt te beginnen | experimental |
De dispatcher, de provider, de marker-interface en de basisklasse zijn stable (sinds 3.0.0). De event-payloads zijn experimental. Hun constructorargumenten en readonly-eigenschappen kunnen in een minor release veranderen. Patch-releases voegen alleen toe. Houd bij koppeling aan payload-eigenschapsnamen rekening met die beperking.
API-oppervlak
Sectie met titel “API-oppervlak”NextPDF\Event\ListenerProvider (stable, final):
| Methode | Geeft terug | Doel |
|---|---|---|
addListener(string $eventClass, callable $listener, int $priority = 0) | void | Registreer een listener; een hogere prioriteit wordt eerst uitgevoerd. Werpt InvalidConfigException wanneer de klasse leeg is. |
getListenersForEvent(EventInterface $event) | list<callable> | Bepaal listeners, inclusief registraties op bovenliggende klassen en interfaces. |
hasListeners(string $eventClass) | bool | Controleer de klassenhiërarchie zonder overhead. |
getListenerCount(string $eventClass) | int | Tel alleen directe registraties. |
clearListeners() | void | Reset de provider. |
NextPDF\Event\EventDispatcher (stable, final):
| Methode | Geeft terug | Doel |
|---|---|---|
dispatch(EventInterface $event) | EventInterface | Roept listeners aan op volgorde van prioriteit, respecteert propagatiestops en geeft het event terug. |
getListenerProvider() | ListenerProvider | Geeft toegang tot de provider om tijdens runtime listeners toe te voegen. |
Documenten die events versturen, gebruiken NextPDF\Event\EventAwareDocumentTrait. De methode setEventDispatcher() van die trait koppelt een dispatcher aan één document. Zonder dispatcher doet elke dispatch-helper niets.
Codevoorbeeld — Snelstart
Sectie met titel “Codevoorbeeld — Snelstart”<?php
declare(strict_types=1);
use NextPDF\Event\EventDispatcher;use NextPDF\Event\ListenerProvider;use NextPDF\Event\Security\SignatureAppliedEvent;
$listeners = new ListenerProvider();$listeners->addListener( SignatureAppliedEvent::class, static function (SignatureAppliedEvent $event): void { \error_log("Signed at level {$event->signatureLevel} by {$event->signerName}"); }, priority: 100,);
$dispatcher = new EventDispatcher($listeners);Codevoorbeeld — Productie
Sectie met titel “Codevoorbeeld — Productie”Deze auditlistener voor productie gebruikt een hoge prioriteit zodat hij als eerste wordt uitgevoerd, schrijft gestructureerde logs en voegt voor de volledigheid een catch-all op de basisklasse toe.
<?php
declare(strict_types=1);
use NextPDF\Event\AbstractEvent;use NextPDF\Event\EventDispatcher;use NextPDF\Event\ListenerProvider;use NextPDF\Event\Security\EncryptionAppliedEvent;use NextPDF\Event\Security\SignatureAppliedEvent;use Psr\Log\LoggerInterface;
final class SecurityAuditSubscriber{ public function __construct(private readonly LoggerInterface $logger) {}
public function register(ListenerProvider $listeners): EventDispatcher { $listeners->addListener( SignatureAppliedEvent::class, function (SignatureAppliedEvent $event): void { $this->logger->info('signature.applied', [ 'level' => $event->signatureLevel, 'signer' => $event->signerName, ]); }, priority: 1000, );
$listeners->addListener( EncryptionAppliedEvent::class, function (EncryptionAppliedEvent $event): void { $this->logger->info('encryption.applied', [ 'algorithm' => $event->algorithm, ]); }, priority: 1000, );
// Catch-all: observe every lifecycle event for trace completeness. $listeners->addListener( AbstractEvent::class, fn (AbstractEvent $event): mixed => $this->logger->debug('lifecycle', ['event' => $event->getEventName()]), priority: -1000, );
return new EventDispatcher($listeners); }}Randgevallen en valkuilen
Sectie met titel “Randgevallen en valkuilen”- Final-klassen.
EventDispatcherenListenerProviderzijnfinal. Stel ze samen via compositie; maak er geen subklasse van. - Lege event-klasse werpt een fout.
addListener('', ...)werptInvalidConfigException. Geef altijd een class-string-constante door. - Wildcard-kosten. Een listener op
AbstractEventwordt bij elk event geactiveerd. Geef catch-all-listeners een lage prioriteit en houd ze lichtgewicht. - Uitvoermutatie.
DocumentOutputEventdraagt bytes in Portable Document Format (PDF). De engine leest ze na de dispatch weer in. Als u die bytes wijzigt, krijgt u veel controle en ook veel risico. Een verkeerde byte-offset beschadigt de PDF en kan een handtekening breken. Observeer bij voorkeur, tenzij u het resultaat zelf beheert met het oog op determinisme en handtekeningen. - Geen dispatcher, geen events. Een document waarvoor via
EventAwareDocumentTraitgeen dispatcher is ingesteld, verstuurt geen events. Dit is het beoogde snelpad zonder overhead, geen installatiefout.
Prestaties
Sectie met titel “Prestaties”Het snelpad bestaat uit één controle van de bovenliggende keten met hasListeners(). Zonder listeners is dispatch vrijwel gratis. De provider bewaart de gesorteerde listenerlijst per event-klasse in de cache en wist die cache alleen wanneer de listeners veranderen. Houd listeners niet-blokkerend, want ze worden inline op het renderpad uitgevoerd.
Beveiligingsnotities
Sectie met titel “Beveiligingsnotities”SignatureAppliedEvent en EncryptionAppliedEvent zijn de auditankers. Registreer listeners met hoge prioriteit om ondertekening en versleuteling weg te schrijven naar een fraudebestendige opslag. Stop de keten niet bij een beveiligingsevent, tenzij u latere listeners wilt onderdrukken. Door te stoppen kunt u stilzwijgend audithooks uitschakelen die daarna zouden worden uitgevoerd.
Conformiteit
Sectie met titel “Conformiteit”Deze pagina doet geen normatieve uitspraken buiten PSR-14-compatibiliteit. Die compatibiliteit is uitsluitend gebaseerd op duck typing en vereist het PSR-14-pakket niet.
Commerciële context
Sectie met titel “Commerciële context”NextPDF Enterprise levert geauditeerde listeners voor handtekening- en versleutelingsevents die een fraudebestendig auditlog voeden. Omdat het listener-contract de publieke event-application programming interface (API) is, kunnen uw eigen listeners naast de Enterprise-listeners op dezelfde provider draaien.
Zie ook
Sectie met titel “Zie ook”- Overzicht van extensie-auteurschap
- Aangepaste lettertypen
- Aangepaste lay-out en tekstonderschepping
- Contract voor de Key Management Service (KMS)-provider
- Stabiliteitsregels voor de Service Provider Interface (SPI)
Verwante contracten en modules
Sectie met titel “Verwante contracten en modules”- Referentie van de Event-module — de PSR-14-taxonomie van lifecycle-events en de interne werking van de dispatcher.
- Referentie van de ondertekeningscontracten — de contracten achter
SignatureAppliedEvent. - SPI-stabiliteitsregels — hoe de stabiele dispatcher en de experimentele payloads worden geversioneerd.
- Aangepaste lettertypen — koppelt
FontLoadedEventaan het registry-contract. - Overzicht van extensie-auteurschap — het volledige publieke SPI-oppervlak.
De woordenlijst definieert de termen event listener, event dispatcher, listener provider en stoppable event die op deze pagina worden gebruikt. Raadpleeg de gepubliceerde woordenlijst voor canonieke definities.