Event: PSR-14 yaşam döngüsü olayı sınıflandırması
Bir bakışta
“Bir bakışta” başlıklı bölümEvent modülü, PDF üretiminin her aşamasında tipli yaşam döngüsü olayları gönderir. Dinleyiciler, motorun iç yapısını değiştirmeden bir belgeyi gözlemleyebilir veya dönüştürebilir. Dağıtıcı, PHP Standards Recommendation 14 (PSR-14) standardını izler; bu nedenle mevcut PSR-14 araçlarıyla uyumluluk korunur.
Kurulum
“Kurulum” başlıklı bölümcomposer require nextpdf/core:^3Event modülü, core paketiyle birlikte gelir. Ek bağımlılığı yoktur: EventInterface ve StoppableEventInterface türleri, psr/event-dispatcher paketini gerektirmeden PSR-14 sözleşmelerini karşılar.
Kavramsal genel bakış
“Kavramsal genel bakış” başlıklı bölümModül üç bölümden oluşur: bir dağıtıcı, bir dinleyici sağlayıcı ve sabit bir yaşam döngüsü olayı sınıfları kümesi.
EventDispatcher bir EventInterface örneği alır, eşleşen dinleyiciler için ListenerProvider öğesini sorgular ve her birini öncelik sırasına göre çağırır. dispatch() yöntemi aynı olay nesnesini döndürür. Bir dinleyici, motorun olaya yerleştirdiği durumu okuyabilir ve motorun daha sonra okuyacağı durumu geri yazabilir. Bu davranış, PSR-14 dağıtıcı modeliyle örtüşür.
ListenerProvider, bir olay sınıfını öncelik sırasına göre düzenlenmiş çağrılabilirler listesiyle eşler. Kayıt örnek kapsamındadır ve statik durum içermez; böylece bir işçi süreci kendi sağlayıcı örneklerini tutabilir. Sağlayıcı, olay sınıfı ağacında ve ilgili arabirimlerde de dolaşır. AbstractEvent üzerinde kayıtlı bir dinleyici, her yaşam döngüsü olayını görür. Bir arabirim üzerinde kayıtlı bir dinleyici, onu uygulayan her olayı görür.
StoppableEventInterface, yayılım denetimi ekler. Bir dinleyici stopPropagation() çağırabilir; dağıtıcı da o döngüde sonraki dinleyicileri çağırmayı durdurur. Durdurulabilir olay, dinleyici zincirini durdurma yolunu kendi üzerinde taşıyan özel bir olaydır. PSR-14, durdurulabilir olaylar için aynı modeli kullanır (PSR-14 psr_14_event#x4). AbstractEvent, arabirimi StoppableEventTrait aracılığıyla uygular; böylece her yaşam döngüsü olayı varsayılan olarak durdurulabilir.
Dağıtıcının ek yükü sıfıra yakın bir hızlı yolu vardır. Olay sınıfında veya herhangi bir atasında dinleyici olup olmadığını denetler. Hiçbiri yoksa hasListeners() false döndürür ve dispatch() hemen geri döner. Dinleyicisi olmayan bir belgenin maliyeti, her yaşam döngüsü noktası başına bir boole denetimiyle sınırlıdır.
EventAwareDocumentTrait, tümleştirme noktasıdır. İsteğe bağlı bir EventDispatcher tutar ve korumalı dağıtım yardımcılarını açığa çıkarır. Document sınıfı, bu yardımcıları her yaşam döngüsü noktasında çağırır. Dağıtıcı ayarlanmadığında, her yardımcı işlemsizdir.
Yaşam döngüsü sınıflandırması şu olayları kapsar:
| Olay | Ad alanı | Tetiklenme |
|---|---|---|
DocumentCreatedEvent | Event\Document | Belge tamamen oluşturulduktan sonra |
PageAddedEvent | Event\Document | Sayfa başlatıldıktan sonra |
ContentRenderedEvent | Event\Content | Sayfaya HTML veya metin içeriği işlendikten sonra |
FontLoadedEvent | Event\Content | Yazı tipi bir kayda ayrıştırıldığında |
EncryptionAppliedEvent | Event\Security | Şifreleme parametreleri yapılandırıldıktan sonra |
SignatureAppliedEvent | Event\Security | Bir imza gömüldükten sonra |
PdfSerializedEvent | Event\Writer | Serileştirmeden sonra, çıktı teslimatından önce |
DocumentOutputEvent | Event\Document | PDF baytları hedefe ulaşmadan önce |
API yüzeyi
“API yüzeyi” başlıklı bölüm| Simge | Tür | Temel üyeler |
|---|---|---|
NextPDF\Event\EventInterface | arabirim | getEventName(): non-empty-string |
NextPDF\Event\StoppableEventInterface | arabirim | isPropagationStopped(): bool |
NextPDF\Event\StoppableEventTrait | trait | isPropagationStopped(), stopPropagation() |
NextPDF\Event\AbstractEvent | soyut sınıf | getEventName(); uyguladığı arabirim: StoppableEventInterface |
NextPDF\Event\EventDispatcher | final sınıf | dispatch(EventInterface): EventInterface, getListenerProvider() |
NextPDF\Event\ListenerProvider | final sınıf | addListener(), getListenersForEvent(), hasListeners(), getListenerCount(), clearListeners() |
NextPDF\Event\EventAwareDocumentTrait | trait | setEventDispatcher(), getEventDispatcher() |
NextPDF\Event\Document\DocumentCreatedEvent | final sınıf | $document, $config |
NextPDF\Event\Document\PageAddedEvent | final sınıf | $document, $pageIndex, $pageSize, $orientation |
NextPDF\Event\Document\DocumentOutputEvent | final sınıf | getPdfData(), setPdfData(), getByteSize(), $filename, $destination |
NextPDF\Event\Content\ContentRenderedEvent | final sınıf | $document, $pageIndex, $contentType, $content |
NextPDF\Event\Content\FontLoadedEvent | final sınıf | $family, $style, $fontType, $filePath |
NextPDF\Event\Security\EncryptionAppliedEvent | final sınıf | $document, $algorithm, $allowPrint, $allowCopy, $allowModify |
NextPDF\Event\Security\SignatureAppliedEvent | final sınıf | $document, $signatureLevel, $signerName, $reason, $location |
NextPDF\Event\Writer\PdfSerializedEvent | final sınıf | $byteSize, $objectCount, $pageCount, $pdfVersion, $isLinearized, $isEncrypted |
addListener(), olay sınıfı dizesi boşsa NextPDF\Exception\InvalidConfigException fırlatır.
Kod örneği — hızlı başlangıç
“Kod örneği — hızlı başlangıç” başlıklı bölümBir dinleyici kaydedin, ardından bir yaşam döngüsü olayı gönderin.
<?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);Dağıtıcı eklendikten sonra Document sınıfı dağıtım yardımcılarını dahili olarak çağırır; dağıtıcı setEventDispatcher() aracılığıyla iliştirilir.
Kod örneği — üretim
“Kod örneği — üretim” başlıklı bölümDağıtıcıyı bir belgeye bağlayın, dinleyici önceliğini ayarlayın ve geçit dinleyicisinden yayılımı durdurun.
<?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).Uç durumlar ve ince noktalar
“Uç durumlar ve ince noktalar” başlıklı bölüm- Joker karakterli kayıt, sınıf hiyerarşisini kullanır.
AbstractEventüzerindeki bir dinleyici, her olay onu genişlettiği için her yaşam döngüsü olayını alır. Yalnızca tek bir olay istediğinizde, dinleyicileri somut sınıflarla sınırlandırın. - Dinleyici önceliği, en yüksek önce olacak şekilde sıralanır. Eşit öncelikler ekleme sırasını korur (kararlı sıralama).
stopPropagation()yalnızca geçerli dağıtım döngüsünü durdurur. Bir sonraki gönderilen olay, yeni bir döngü başlatır.- Yeni bir üst sınıf veya arabirim kaydı, birkaç olay sınıfı için çözümlemeyi değiştirebileceğinden, sıralanmış dinleyici önbelleği herhangi bir
addListener()çağrısında geçersiz kılınır. $document, belge kapsamındaki olaylardaobjectolarak türlenir;Documentsınıfı olarak değil. Bu, Event modülünü katı birCorebağımlılığına bağlamamak içindir.DocumentOutputEvent::setPdfData()boş olmayan bir dize bekler. Yükü boş bir dizeyle değiştirmek geçersiz bir belge üretir.- Dağıtım yardımcıları,
EventAwareDocumentTraitüzerinde bir dağıtıcı ayarlanana kadar işlemsizdir; bu nedenle dinleyicisiz çalıştırmalar ölçülebilir bir maliyet eklemez.
Performans
“Performans” başlıklı bölümDinleyici olmadığında dağıtım, bir yaprak olay sınıfı için O(1)‘dir: bir hasListeners() boole denetimi ve ardından anında geri dönüş. Dinleyiciler varsa, getListenersForEvent() olay soyağacında bir kez dolaşır, toplanan girdileri sıralar ve sonraki değişikliğe kadar sıralanmış listeyi olay sınıfı başına önbelleğe alır. Bu nedenle aynı sınıf için yinelenen dağıtım, eşleşen k dinleyici üzerinden O(k)‘dir. Bu başvuru sayfası için varsayılan performance_budget değeri wall_ms: 1500, peak_mb: 64 şeklindedir.
Güvenlik notları
“Güvenlik notları” başlıklı bölümDinleyiciler, üretim hattı içinde çağıran tarafla aynı ayrıcalıklarla çalışır. Dinleyici kodunu güvenilir kod olarak değerlendirin. DocumentOutputEvent, nihai PDF ikili verisini açığa çıkarır ve bir dinleyicinin onu değiştirmesine izin verir. Denetim veya bütünlük dinleyicisi, baytları dönüştüren herhangi bir dinleyiciden önce çalışmalıdır. Daha yüksek bir öncelik kullanın. Güvenlik kapsamındaki olaylar (EncryptionAppliedEvent, SignatureAppliedEvent), denetim günlüğü için uygulanan parametreleri bildirir. Bunlar, kriptografik sonucu değiştirmez.
Uyumluluk
“Uyumluluk” başlıklı bölüm| Belirtim | Madde | Konu |
|---|---|---|
| PSR-14 (PHP-FIG) | psr_14_event#x4 | Durdurulabilir olay, sonraki dinleyicileri durdurur |
Hem dispatch() imzası hem dinleyici-sağlayıcı ayrımı hem de durdurulabilir olay modeli PSR-14 standardını izler. NextPDF kendi EventInterface ve StoppableEventInterface arabirimlerini bildirir. Paketin PSR-14 çalışma zamanı bağımlılığı yoktur, ancak duck-type uyumluluğunu korur.
Ayrıca bkz.
“Ayrıca bkz.” başlıklı bölüm/modules/core/contracts/— genel arabirim yüzeyi/modules/core/observability/— telemetri ve metrik kancaları/modules/core/audit/— denetim izi tümleştirmesi/modules/core/config/—Config, iletildiği olay:DocumentCreatedEvent/modules/core/exception/—InvalidConfigException, fırlatıldığı çağrı:addListener()
Sözlük: PSR-14 · durdurulabilir olay · dinleyici sağlayıcı