Trình kích hoạt hành động và trình lắng nghe sự kiện
Nhìn nhanh
Phần tiêu đề “Nhìn nhanh”NextPDF phát ra các sự kiện vòng đời thông qua hệ thống trong NextPDF\Event tương thích với PHP Standards Recommendation 14 (PSR-14). Hãy đăng ký một trình lắng nghe, chọn mức ưu tiên và phản ứng khi tài liệu được tạo, trang được thêm, phông chữ được nạp, tác vụ ký hoặc mã hóa chạy, byte được ghi, hoặc quá trình xuất bắt đầu. Chỉ dừng chuỗi khi thật sự cần.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/core:^3Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”Hệ thống sự kiện có hai phần công khai. ListenerProvider ánh xạ từng lớp sự kiện tới một danh sách trình lắng nghe callable đã được sắp xếp. EventDispatcher duyệt danh sách đó và gọi từng trình lắng nghe theo thứ tự ưu tiên. Cả hai lớp đều là final, vì vậy hãy mở rộng hành vi bằng cách kết hợp, không phải bằng kế thừa lớp con.
Cả hai lớp đều khớp với PSR-14 thông qua duck typing. EventDispatcher::dispatch() dùng chữ ký dispatch() của PSR-14 và trả về sự kiện sau khi mọi trình lắng nghe chạy xong. ListenerProvider::getListenersForEvent() dùng chữ ký provider của PSR-14. NextPDF không yêu cầu gói PSR-14; nếu dự án của bạn cài gói đó, các interface vẫn khớp với nhau.
Có hai hành vi quan trọng đối với người viết tiện ích mở rộng:
- Lắng nghe wildcard. Để phân giải trình lắng nghe, provider duyệt qua các lớp cha và interface của sự kiện. Gắn một trình lắng nghe vào lớp cơ sở
AbstractEventđể theo dõi mọi sự kiện vòng đời. Gắn một trình lắng nghe vào một interface để bắt trọn một họ sự kiện. - Ưu tiên và lan truyền. Mức ưu tiên cao hơn chạy trước. Các mức ưu tiên bằng nhau giữ nguyên thứ tự đăng ký. Mọi sự kiện kế thừa
AbstractEventđều có thể dừng được. Một trình lắng nghe có thể gọistopPropagation(), và khi đó bộ điều phối sẽ bỏ qua phần còn lại.
Bộ điều phối có một đường tắt không tốn chi phí. Khi không có trình lắng nghe nào được gắn với một lớp sự kiện hoặc bất kỳ lớp cha nào của lớp đó, dispatch() trả về ngay sau một lần kiểm tra hasListeners().
Các sự kiện vòng đời
Phần tiêu đề “Các sự kiện vòng đời”| Sự kiện | Namespace | Phát ra khi | Độ ổn định |
|---|---|---|---|
DocumentCreatedEvent | NextPDF\Event\Document | Quá trình dựng tài liệu hoàn tất | experimental |
PageAddedEvent | NextPDF\Event\Document | Một trang đã được khởi tạo đầy đủ | experimental |
ContentRenderedEvent | NextPDF\Event\Content | Nội dung được kết xuất ra một trang | experimental |
FontLoadedEvent | NextPDF\Event\Content | Một họ phông chữ và kiểu chữ được nạp lần đầu tiên | experimental |
SignatureAppliedEvent | NextPDF\Event\Security | Các byte chữ ký được nhúng | experimental |
EncryptionAppliedEvent | NextPDF\Event\Security | Mã hóa đã được cấu hình | experimental |
PdfSerializedEvent | NextPDF\Event\Writer | Quá trình tuần tự hóa hoàn tất | experimental |
DocumentOutputEvent | NextPDF\Event\Document | Quá trình phân phối đầu ra sắp bắt đầu | experimental |
Bộ điều phối, provider, interface đánh dấu và lớp cơ sở là stable (kể từ 3.0.0). Các payload sự kiện là experimental. Đối số khởi tạo và thuộc tính readonly của chúng có thể thay đổi trong một bản phát hành minor. Các bản phát hành patch chỉ bổ sung. Hãy dựa vào tên thuộc tính của payload với ràng buộc đó trong đầu.
Bề mặt API
Phần tiêu đề “Bề mặt API”NextPDF\Event\ListenerProvider (stable, final):
| Phương thức | Trả về | Mục đích |
|---|---|---|
addListener(string $eventClass, callable $listener, int $priority = 0) | void | Đăng ký một trình lắng nghe; mức ưu tiên cao hơn chạy trước. Ném InvalidConfigException khi lớp rỗng. |
getListenersForEvent(EventInterface $event) | list<callable> | Phân giải các trình lắng nghe, bao gồm cả đăng ký trên lớp cha và interface. |
hasListeners(string $eventClass) | bool | Kiểm tra cây phân cấp lớp với chi phí bằng không. |
getListenerCount(string $eventClass) | int | Chỉ đếm các đăng ký trực tiếp. |
clearListeners() | void | Đặt lại provider. |
NextPDF\Event\EventDispatcher (stable, final):
| Phương thức | Trả về | Mục đích |
|---|---|---|
dispatch(EventInterface $event) | EventInterface | Gọi các trình lắng nghe theo thứ tự ưu tiên, tôn trọng các điểm dừng lan truyền và trả về sự kiện. |
getListenerProvider() | ListenerProvider | Truy cập provider để thêm trình lắng nghe lúc chạy. |
Các tài liệu phát ra sự kiện sử dụng NextPDF\Event\EventAwareDocumentTrait. Phương thức setEventDispatcher() của trait này gắn một bộ điều phối vào tài liệu. Khi không có bộ điều phối, mọi hàm trợ giúp dispatch đều không làm gì.
Mẫu mã — bắt đầu nhanh
Phần tiêu đề “Mẫu mã — bắt đầu nhanh”<?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);Mẫu mã — dùng trong sản xuất
Phần tiêu đề “Mẫu mã — dùng trong sản xuất”Trình lắng nghe audit dùng trong sản xuất này đặt mức ưu tiên cao để chạy trước, ghi log có cấu trúc và thêm một trình bắt-tất-cả trên lớp cơ sở để bảo đảm đầy đủ.
<?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); }}Trường hợp biên & lưu ý
Phần tiêu đề “Trường hợp biên & lưu ý”- Các lớp final.
EventDispatchervàListenerProviderlàfinal. Hãy kết hợp chúng; đừng tạo lớp con từ chúng. - Lớp sự kiện rỗng sẽ ném lỗi.
addListener('', ...)némInvalidConfigException. Luôn truyền vào một hằng class-string. - Chi phí wildcard. Một trình lắng nghe trên
AbstractEventđược kích hoạt với mọi sự kiện. Hãy đặt mức ưu tiên thấp cho các trình lắng nghe bắt-tất-cả và giữ chúng thật nhẹ. - Thay đổi đầu ra.
DocumentOutputEventmang các byte Portable Document Format (PDF). Engine đọc lại các byte này sau khi dispatch. Nếu thay đổi chúng, bạn có quyền kiểm soát rộng nhưng cũng gánh rủi ro lớn. Chỉ một byte offset sai cũng sẽ làm hỏng PDF và có thể phá vỡ chữ ký. Hãy ưu tiên quan sát, trừ khi bạn tự chịu trách nhiệm cho kết quả về tính tất định và chữ ký. - Không có bộ điều phối thì không có sự kiện. Tài liệu không được đặt bộ điều phối thông qua
EventAwareDocumentTraitsẽ không phát ra sự kiện nào. Đây là đường không tốn chi phí có chủ đích, không phải lỗi thiết lập.
Hiệu năng
Phần tiêu đề “Hiệu năng”Đường tắt là một lần kiểm tra chuỗi lớp cha bằng hasListeners(). Khi không có trình lắng nghe nào, việc dispatch gần như miễn phí. Provider lưu vào bộ nhớ đệm danh sách trình lắng nghe đã sắp xếp cho từng lớp sự kiện và chỉ xóa bộ nhớ đệm đó khi trình lắng nghe thay đổi. Hãy giữ cho các trình lắng nghe không chặn vì chúng chạy nội tuyến trên đường kết xuất.
Lưu ý bảo mật
Phần tiêu đề “Lưu ý bảo mật”SignatureAppliedEvent và EncryptionAppliedEvent là các neo audit. Đăng ký các trình lắng nghe có mức ưu tiên cao để ghi log việc ký và mã hóa vào kho chống giả mạo. Đừng dừng chuỗi trên sự kiện bảo mật trừ khi bạn chủ ý làm câm các trình lắng nghe chạy sau. Việc dừng chuỗi có thể âm thầm vô hiệu hóa các hook audit chạy sau đó.
Tuân thủ
Phần tiêu đề “Tuân thủ”Trang này không đưa ra tuyên bố mang tính chuẩn mực nào ngoài khả năng tương thích với PSR-14. Khả năng tương thích đó chỉ ở mức duck-type và không yêu cầu gói PSR-14.
Bối cảnh thương mại
Phần tiêu đề “Bối cảnh thương mại”NextPDF Enterprise cung cấp sẵn các trình lắng nghe đã được kiểm toán cho sự kiện chữ ký và mã hóa, đưa dữ liệu vào nhật ký audit chống giả mạo. Vì hợp đồng trình lắng nghe chính là application programming interface (API) sự kiện công khai, các trình lắng nghe của riêng bạn có thể cùng tồn tại với trình lắng nghe của Enterprise trên cùng một provider.
Xem thêm
Phần tiêu đề “Xem thêm”- Tổng quan về viết tiện ích mở rộng
- Phông chữ tùy chỉnh
- Bố cục tùy chỉnh và chặn văn bản
- Hợp đồng provider Key Management Service (KMS)
- Quy tắc ổn định Service Provider Interface (SPI)
Các hợp đồng và mô-đun liên quan
Phần tiêu đề “Các hợp đồng và mô-đun liên quan”- Tham chiếu mô-đun Event — phân loại sự kiện vòng đời theo PSR-14 và phần nội bộ của bộ điều phối.
- Tham chiếu hợp đồng ký — các hợp đồng đứng sau
SignatureAppliedEvent. - Quy tắc ổn định SPI — cách bộ điều phối stable và các payload experimental được đánh phiên bản.
- Phông chữ tùy chỉnh — ghép
FontLoadedEventvới hợp đồng registry. - Tổng quan về viết tiện ích mở rộng — toàn bộ bề mặt SPI công khai.
Bảng thuật ngữ định nghĩa các thuật ngữ event listener, event dispatcher, listener provider và stoppable event được dùng trên trang này. Hãy xem bảng thuật ngữ đã xuất bản để biết các định nghĩa chuẩn tắc.