Event: PSR-14-taxonomie voor levenscyclusgebeurtenissen
In het kort
Sectie met titel “In het kort”De Event-module verstuurt getypeerde levenscyclusgebeurtenissen tijdens elke fase van de PDF-generatie. Listeners kunnen een document observeren of transformeren zonder de interne werking van de engine te wijzigen. De dispatcher volgt PHP Standards Recommendation 14 (PSR-14), zodat bestaande PSR-14-tooling compatibel blijft.
Installatie
Sectie met titel “Installatie”composer require nextpdf/core:^3De Event-module wordt meegeleverd met het core-pakket. De module heeft geen extra afhankelijkheden: de typen EventInterface en StoppableEventInterface weerspiegelen de PSR-14-contracten zonder dat het pakket psr/event-dispatcher vereist is.
Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”De module bestaat uit drie delen: een dispatcher, een listener-provider en een vaste set klassen voor levenscyclusgebeurtenissen.
EventDispatcher ontvangt een EventInterface-instance, vraagt de ListenerProvider om bijbehorende listeners en roept elke listener in volgorde van prioriteit aan. De methode dispatch() retourneert hetzelfde event-object. Een listener kan de status lezen die de engine in de gebeurtenis heeft geplaatst en status terugschrijven die de engine later leest. Dit komt overeen met het PSR-14-dispatchermodel.
ListenerProvider koppelt een event-klasse aan een lijst met aanroepbare functies in volgorde van prioriteit. Registratie is gebonden aan een instance, zonder statische status, zodat een worker-proces zijn eigen provider-instances kan aanhouden. De provider doorloopt ook de klassenboom van de gebeurtenis, inclusief de bijbehorende interfaces. Een listener op AbstractEvent ontvangt elke levenscyclusgebeurtenis. Een listener op een interface ontvangt elke gebeurtenis die deze implementeert.
StoppableEventInterface voegt propagatiebeheer toe. Een listener kan stopPropagation() aanroepen, waarna de dispatcher stopt met het aanroepen van latere listeners voor die cyclus. Een stopbare gebeurtenis draagt zelf de mogelijkheid mee om de listenerketen te stoppen. PSR-14 gebruikt hetzelfde model voor stopbare gebeurtenissen (PSR-14 psr_14_event#x4). AbstractEvent implementeert de interface via StoppableEventTrait, zodat elke levenscyclusgebeurtenis standaard stopbaar is.
De dispatcher heeft een snelpad zonder overhead. Hij controleert of er een listener is voor de event-klasse of een van de voorouders. Als die er niet is, retourneert hasListeners() false en keert dispatch() meteen terug. Een document zonder listeners kost per levenscycluspunt één booleaanse controle.
EventAwareDocumentTrait is het integratiepunt. Hij houdt een optionele EventDispatcher aan en stelt protected dispatch-helpers beschikbaar. De klasse Document roept deze helpers aan bij elk levenscycluspunt. Wanneer er geen dispatcher is ingesteld, is elke helper een no-op.
De levenscyclustaxonomie omvat deze gebeurtenissen:
| Gebeurtenis | Namespace | Geactiveerd |
|---|---|---|
DocumentCreatedEvent | Event\Document | Nadat een document volledig is opgebouwd |
PageAddedEvent | Event\Document | Nadat een pagina is geïnitialiseerd |
ContentRenderedEvent | Event\Content | Nadat HTML- of tekstinhoud op een pagina is gerenderd |
FontLoadedEvent | Event\Content | Wanneer een lettertype in het register wordt geparseerd |
EncryptionAppliedEvent | Event\Security | Nadat de versleutelingsparameters zijn geconfigureerd |
SignatureAppliedEvent | Event\Security | Nadat een handtekening is ingebed |
PdfSerializedEvent | Event\Writer | Na serialisatie, vóór de afgifte van de uitvoer |
DocumentOutputEvent | Event\Document | Voordat de PDF-bytes de bestemming bereiken |
API-oppervlak
Sectie met titel “API-oppervlak”| Symbool | Soort | Belangrijkste leden |
|---|---|---|
NextPDF\Event\EventInterface | interface | getEventName(): non-empty-string |
NextPDF\Event\StoppableEventInterface | interface | isPropagationStopped(): bool |
NextPDF\Event\StoppableEventTrait | trait | isPropagationStopped(), stopPropagation() |
NextPDF\Event\AbstractEvent | abstracte klasse | getEventName(); implementeert StoppableEventInterface |
NextPDF\Event\EventDispatcher | final class | dispatch(EventInterface): EventInterface, getListenerProvider() |
NextPDF\Event\ListenerProvider | final class | addListener(), getListenersForEvent(), hasListeners(), getListenerCount(), clearListeners() |
NextPDF\Event\EventAwareDocumentTrait | trait | setEventDispatcher(), getEventDispatcher() |
NextPDF\Event\Document\DocumentCreatedEvent | final class | $document, $config |
NextPDF\Event\Document\PageAddedEvent | final class | $document, $pageIndex, $pageSize, $orientation |
NextPDF\Event\Document\DocumentOutputEvent | final class | getPdfData(), setPdfData(), getByteSize(), $filename, $destination |
NextPDF\Event\Content\ContentRenderedEvent | final class | $document, $pageIndex, $contentType, $content |
NextPDF\Event\Content\FontLoadedEvent | final class | $family, $style, $fontType, $filePath |
NextPDF\Event\Security\EncryptionAppliedEvent | final class | $document, $algorithm, $allowPrint, $allowCopy, $allowModify |
NextPDF\Event\Security\SignatureAppliedEvent | final class | $document, $signatureLevel, $signerName, $reason, $location |
NextPDF\Event\Writer\PdfSerializedEvent | final class | $byteSize, $objectCount, $pageCount, $pdfVersion, $isLinearized, $isEncrypted |
addListener() gooit NextPDF\Exception\InvalidConfigException wanneer de tekenreeks van de event-klasse leeg is.
Codevoorbeeld — Snelstart
Sectie met titel “Codevoorbeeld — Snelstart”Registreer een listener en verstuur vervolgens een levenscyclusgebeurtenis.
<?php
declare(strict_types=1);
use NextPDF\Event\Document\PageAddedEvent;use NextPDF\Event\EventDispatcher;use NextPDF\Event\ListenerProvider;
$provider = new ListenerProvider();$provider->addListener( PageAddedEvent::class, static function (PageAddedEvent $event): void { \printf("Page %d added (%s)\n", $event->pageIndex, $event->pageSize->name); },);
$dispatcher = new EventDispatcher($provider);De klasse Document roept de dispatch-helpers intern aan nadat een dispatcher via setEventDispatcher() is gekoppeld.
Codevoorbeeld — Productie
Sectie met titel “Codevoorbeeld — Productie”Koppel de dispatcher aan een document, stel de listenerprioriteit in en laat een gate-listener de propagatie stoppen.
<?php
declare(strict_types=1);
use NextPDF\Event\Document\DocumentOutputEvent;use NextPDF\Event\Document\PageAddedEvent;use NextPDF\Event\EventDispatcher;use NextPDF\Event\ListenerProvider;
$provider = new ListenerProvider();
// Higher priority runs first. A licensing gate observes every page.$provider->addListener( PageAddedEvent::class, static function (PageAddedEvent $event): void { if ($event->pageIndex >= 100) { // Stop later page listeners for this dispatch cycle. $event->stopPropagation(); } }, priority: 100,);
// Last-chance hook: replace the PDF bytes before delivery.$provider->addListener( DocumentOutputEvent::class, static function (DocumentOutputEvent $event): void { $optimized = \gzencode($event->getPdfData(), 0); if ($optimized !== false) { $event->setPdfData($optimized); } },);
$dispatcher = new EventDispatcher($provider);// Pass $dispatcher to a Document via setEventDispatcher($dispatcher).Randgevallen en valkuilen
Sectie met titel “Randgevallen en valkuilen”- Wildcard-registratie gebruikt de klassenhiërarchie. Een listener op
AbstractEventontvangt elke levenscyclusgebeurtenis, omdat elke gebeurtenis deze uitbreidt. Beperk listeners tot concrete klassen wanneer je slechts één gebeurtenis wilt verwerken. - Listeners met de hoogste prioriteit worden als eerste uitgevoerd. Gelijke prioriteiten behouden de invoegvolgorde (stabiele sortering).
stopPropagation()stopt alleen de huidige dispatch-cyclus. De volgende verstuurde gebeurtenis start een nieuwe cyclus.- De gesorteerde listener-cache wordt bij elke aanroep van
addListener()ongeldig gemaakt, omdat een nieuwe registratie van een ouder of interface de resolutie voor meerdere event-klassen kan wijzigen. $documentop documentgebonden gebeurtenissen is getypeerd alsobject, niet als de klasseDocument, om de Event-module vrij te houden van een hardeCore-afhankelijkheid.DocumentOutputEvent::setPdfData()verwacht een niet-lege tekenreeks. Het vervangen van de payload door een lege tekenreeks levert een ongeldig document op.- De dispatch-helpers op
EventAwareDocumentTraitzijn no-ops totdat er een dispatcher is ingesteld, zodat runs zonder listeners geen meetbare kosten toevoegen.
Prestaties
Sectie met titel “Prestaties”Verzending zonder listeners is O(1) voor een leaf-event-klasse: één booleaanse controle met hasListeners(), waarna direct wordt teruggekeerd. Met listeners doorloopt getListenersForEvent() de event-voorouders eenmaal, sorteert het de verzamelde items en zet het de gesorteerde lijst per event-klasse in de cache tot de volgende mutatie. Een herhaalde verzending van dezelfde klasse is daarom O(k) over k overeenkomende listeners. Het standaard performance_budget voor deze referentiepagina is wall_ms: 1500, peak_mb: 64.
Beveiligingsopmerkingen
Sectie met titel “Beveiligingsopmerkingen”Listeners draaien binnen de generatiepijplijn met dezelfde rechten als de aanroeper. Behandel listener-code als vertrouwde code. DocumentOutputEvent stelt de uiteindelijke PDF-binary beschikbaar en laat een listener deze vervangen. Een auditlistener of integriteitslistener zou moeten draaien vóór elke listener die de bytes transformeert. Gebruik een hogere prioriteit. De beveiligingsgebonden gebeurtenissen (EncryptionAppliedEvent, SignatureAppliedEvent) rapporteren de toegepaste parameters voor auditlogging. Ze wijzigen de cryptografische uitkomst niet.
Conformiteit
Sectie met titel “Conformiteit”| Specificatie | Clausule | Onderwerp |
|---|---|---|
| PSR-14 (PHP-FIG) | psr_14_event#x4 | Stopbare gebeurtenis stopt verdere listeners |
De signatuur van dispatch(), de splitsing van de listener-provider en het stopbare-gebeurtenismodel volgen PSR-14. NextPDF declareert zijn eigen EventInterface en StoppableEventInterface. Het pakket heeft geen PSR-14-runtime-afhankelijkheid en blijft toch duck-type-compatibel.
Zie ook
Sectie met titel “Zie ook”/modules/core/contracts/— publiek interface-oppervlak/modules/core/observability/— telemetrie- en metric-hooks/modules/core/audit/— integratie van het auditspoor/modules/core/config/—Configdoorgegeven bijDocumentCreatedEvent/modules/core/exception/—InvalidConfigExceptionvanaddListener()
Woordenlijst: PSR-14 · stopbare gebeurtenis · listener-provider