Wyzwalacze akcji i nasłuchiwacze zdarzeń
W skrócie
Dział zatytułowany „W skrócie”NextPDF emituje zdarzenia cyklu życia za pośrednictwem systemu w NextPDF\Event, zgodnego z PHP Standards Recommendation 14 (PSR-14). Zarejestruj nasłuchiwacz, wybierz priorytet i reaguj, gdy dokument zostaje utworzony, strona dodana, czcionka załadowana, rozpoczyna się podpisywanie lub szyfrowanie, zapisywane są bajty albo startuje generowanie danych wyjściowych. Zatrzymuj łańcuch tylko wtedy, gdy jest to konieczne.
Instalacja
Dział zatytułowany „Instalacja”composer require nextpdf/core:^3Przegląd koncepcyjny
Dział zatytułowany „Przegląd koncepcyjny”System zdarzeń ma dwie publiczne części. ListenerProvider mapuje każdą klasę zdarzenia na posortowaną listę wywoływalnych nasłuchiwaczy. EventDispatcher przechodzi przez tę listę i wywołuje każdy nasłuchiwacz w kolejności priorytetów. Obie klasy są final, dlatego rozszerzaj ich zachowanie przez kompozycję, a nie przez dziedziczenie.
Obie klasy są zgodne z PSR-14 dzięki kaczemu typowaniu. EventDispatcher::dispatch() używa sygnatury dispatch() z PSR-14 i zwraca zdarzenie po wykonaniu wszystkich nasłuchiwaczy. ListenerProvider::getListenersForEvent() używa sygnatury dostawcy z PSR-14. NextPDF nie wymaga pakietu PSR-14. Jeśli pakiet jest zainstalowany w projekcie, interfejsy nadal się zgadzają.
Dla autorów rozszerzeń istotne są dwa zachowania:
- Nasłuchiwanie wieloznaczne. Aby rozwiązać nasłuchiwacze, dostawca przechodzi przez klasy nadrzędne i interfejsy zdarzenia. Powiąż nasłuchiwacz z klasą bazową
AbstractEvent, aby obserwować każde zdarzenie cyklu życia. Powiąż go z interfejsem, aby objąć całą rodzinę. - Priorytet i propagacja. Nasłuchiwacze o wyższym priorytecie są wykonywane jako pierwsze. Przy równych priorytetach zachowana jest kolejność rejestracji. Każde zdarzenie rozszerzające
AbstractEventmożna zatrzymać. Nasłuchiwacz może wywołaćstopPropagation(), a dyspozytor pomija wtedy pozostałe.
Dyspozytor ma szybką ścieżkę bez narzutu. Gdy dla klasy zdarzenia ani żadnej klasy nadrzędnej nie powiązano nasłuchiwacza, dispatch() zwraca wynik natychmiast po jednym sprawdzeniu hasListeners().
Zdarzenia cyklu życia
Dział zatytułowany „Zdarzenia cyklu życia”| Zdarzenie | Przestrzeń nazw | Emitowane, gdy | Stabilność |
|---|---|---|---|
DocumentCreatedEvent | NextPDF\Event\Document | Kończy się konstruowanie dokumentu | eksperymentalne |
PageAddedEvent | NextPDF\Event\Document | Strona jest w pełni zainicjowana | eksperymentalne |
ContentRenderedEvent | NextPDF\Event\Content | Treść jest renderowana na stronie | eksperymentalne |
FontLoadedEvent | NextPDF\Event\Content | Rodzina i styl czcionki ładują się po raz pierwszy | eksperymentalne |
SignatureAppliedEvent | NextPDF\Event\Security | Bajty podpisu zostają osadzone | eksperymentalne |
EncryptionAppliedEvent | NextPDF\Event\Security | Zostaje skonfigurowane szyfrowanie | eksperymentalne |
PdfSerializedEvent | NextPDF\Event\Writer | Kończy się serializacja | eksperymentalne |
DocumentOutputEvent | NextPDF\Event\Document | Za chwilę rozpocznie się dostarczanie danych wyjściowych | eksperymentalne |
Dyspozytor, dostawca, interfejs znacznikowy i klasa bazowa są stable (od 3.0.0). Ładunki zdarzeń są experimental. Ich argumenty konstruktora i właściwości readonly mogą się zmienić w wydaniu pomocniczym. Wydania poprawkowe wprowadzają wyłącznie dodatki. Opieraj się na nazwach właściwości ładunku z uwzględnieniem tego ograniczenia.
Powierzchnia API
Dział zatytułowany „Powierzchnia API”NextPDF\Event\ListenerProvider (stabilna, final):
| Metoda | Zwraca | Przeznaczenie |
|---|---|---|
addListener(string $eventClass, callable $listener, int $priority = 0) | void | Rejestruje nasłuchiwacz; nasłuchiwacze o wyższym priorytecie są wykonywane jako pierwsze. Zgłasza InvalidConfigException, gdy klasa jest pusta. |
getListenersForEvent(EventInterface $event) | list<callable> | Rozwiązuje nasłuchiwacze, w tym rejestracje na klasach nadrzędnych i interfejsach. |
hasListeners(string $eventClass) | bool | Sprawdza hierarchię klas bez żadnego narzutu. |
getListenerCount(string $eventClass) | int | Zlicza tylko bezpośrednie rejestracje. |
clearListeners() | void | Resetuje dostawcę. |
NextPDF\Event\EventDispatcher (stabilna, final):
| Metoda | Zwraca | Przeznaczenie |
|---|---|---|
dispatch(EventInterface $event) | EventInterface | Wywołuje nasłuchiwacze w kolejności priorytetów, respektuje zatrzymania propagacji i zwraca zdarzenie. |
getListenerProvider() | ListenerProvider | Udostępnia dostawcę, aby dodawać nasłuchiwacze w czasie wykonywania. |
Dokumenty emitujące zdarzenia korzystają z NextPDF\Event\EventAwareDocumentTrait. Jego metoda setEventDispatcher() podłącza dyspozytor do jednego dokumentu. Bez dyspozytora każdy pomocnik wysyłki pozostaje bezczynny.
Przykład kodu — szybki start
Dział zatytułowany „Przykład kodu — szybki start”<?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);Przykład kodu — produkcja
Dział zatytułowany „Przykład kodu — produkcja”Ten produkcyjny nasłuchiwacz audytowy ma wysoki priorytet, więc wykonuje się jako pierwszy; zapisuje ustrukturyzowane logi i dodaje na klasie bazowej obserwator obejmujący wszystkie zdarzenia, aby zapewnić kompletność.
<?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); }}Przypadki brzegowe i pułapki
Dział zatytułowany „Przypadki brzegowe i pułapki”- Klasy final.
EventDispatcheriListenerProvidersąfinal. Komponuj je; nie dziedzicz po nich. - Pusta klasa zdarzenia zgłasza wyjątek.
addListener('', ...)zgłaszaInvalidConfigException. Zawsze przekazuj stałą będącą nazwą klasy (class-string). - Koszt wieloznaczności. Nasłuchiwacz na
AbstractEventuruchamia się dla każdego zdarzenia. Nadawaj nasłuchiwaczom obejmującym wszystko niski priorytet i dbaj, aby były tanie. - Modyfikacja danych wyjściowych.
DocumentOutputEventprzenosi bajty formatu Portable Document Format (PDF). Silnik odczytuje je ponownie po wysyłce. Jeśli zmienisz te bajty, zyskujesz dużą kontrolę, ale bierzesz na siebie duże ryzyko. Błędne przesunięcie bajtu uszkadza PDF i może zepsuć podpis. Domyślnie tylko obserwuj, chyba że odpowiadasz za deterministyczność wyniku i podpisy. - Brak dyspozytora, brak zdarzeń. Dokument bez dyspozytora ustawionego przez
EventAwareDocumentTraitnie emituje żadnych zdarzeń. To zamierzona ścieżka bez narzutu, a nie błąd konfiguracji.
Wydajność
Dział zatytułowany „Wydajność”Szybka ścieżka sprowadza się do jednego sprawdzenia łańcucha klas nadrzędnych przez hasListeners(). Bez nasłuchiwaczy wysyłka jest niemal darmowa. Dostawca buforuje posortowaną listę nasłuchiwaczy dla każdej klasy zdarzenia i czyści ten bufor tylko wtedy, gdy nasłuchiwacze się zmieniają. Dbaj, aby nasłuchiwacze były nieblokujące, ponieważ działają bezpośrednio na ścieżce renderowania.
Uwagi dotyczące bezpieczeństwa
Dział zatytułowany „Uwagi dotyczące bezpieczeństwa”SignatureAppliedEvent i EncryptionAppliedEvent to kotwice audytu. Rejestruj nasłuchiwacze o wysokim priorytecie, aby zapisywać podpisywanie i szyfrowanie do magazynu z wykrywaniem manipulacji. Nie zatrzymuj łańcucha na zdarzeniu bezpieczeństwa, chyba że zamierzasz wyciszyć późniejsze nasłuchiwacze. Zatrzymanie go może po cichu wyłączyć punkty zaczepienia audytu, które działają później.
Zgodność
Dział zatytułowany „Zgodność”Ta strona nie zawiera żadnych twierdzeń normatywnych poza zgodnością z PSR-14. Ta zgodność opiera się wyłącznie na kaczym typowaniu i nie wymaga pakietu PSR-14.
Kontekst komercyjny
Dział zatytułowany „Kontekst komercyjny”NextPDF Enterprise dostarcza audytowane nasłuchiwacze zdarzeń podpisywania i szyfrowania, które zasilają dziennik audytu z wykrywaniem manipulacji. Ponieważ kontrakt nasłuchiwacza jest publicznym API zdarzeń, własne nasłuchiwacze mogą współistnieć z tymi z edycji Enterprise w ramach tego samego dostawcy.
Zobacz też
Dział zatytułowany „Zobacz też”- Przegląd tworzenia rozszerzeń
- Czcionki niestandardowe
- Niestandardowy układ i przechwytywanie tekstu
- Kontrakt dostawcy usługi zarządzania kluczami (KMS)
- Reguły stabilności interfejsu dostawcy usług (SPI)
Powiązane kontrakty i moduły
Dział zatytułowany „Powiązane kontrakty i moduły”- Dokumentacja modułu zdarzeń — taksonomia zdarzeń cyklu życia PSR-14 oraz wewnętrzne działanie dyspozytora.
- Dokumentacja kontraktów podpisywania — kontrakty, na których opiera się
SignatureAppliedEvent. - Reguły stabilności SPI — jak wersjonowane są stabilny dyspozytor i eksperymentalne ładunki.
- Czcionki niestandardowe — łączy
FontLoadedEventz kontraktem rejestru. - Przegląd tworzenia rozszerzeń — pełna publiczna powierzchnia SPI.
Słownik definiuje terminy nasłuchiwacz zdarzeń, dyspozytor zdarzeń, dostawca nasłuchiwaczy i zdarzenie zatrzymywalne używane na tej stronie. Kanoniczne definicje znajdziesz w opublikowanym słowniku.