Bỏ qua để đến nội dung

Trình kích hoạt hành động và trình lắng nghe sự kiện

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.

Terminal window
composer require nextpdf/core:^3

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ọi stopPropagation(), 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().

Sự kiệnNamespacePhát ra khiĐộ ổn định
DocumentCreatedEventNextPDF\Event\DocumentQuá trình dựng tài liệu hoàn tấtexperimental
PageAddedEventNextPDF\Event\DocumentMột trang đã được khởi tạo đầy đủexperimental
ContentRenderedEventNextPDF\Event\ContentNội dung được kết xuất ra một trangexperimental
FontLoadedEventNextPDF\Event\ContentMột họ phông chữ và kiểu chữ được nạp lần đầu tiênexperimental
SignatureAppliedEventNextPDF\Event\SecurityCác byte chữ ký được nhúngexperimental
EncryptionAppliedEventNextPDF\Event\SecurityMã hóa đã được cấu hìnhexperimental
PdfSerializedEventNextPDF\Event\WriterQuá trình tuần tự hóa hoàn tấtexperimental
DocumentOutputEventNextPDF\Event\DocumentQuá trình phân phối đầu ra sắp bắt đầuexperimental

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.

NextPDF\Event\ListenerProvider (stable, final):

Phương thứcTrả 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)boolKiểm tra cây phân cấp lớp với chi phí bằng không.
getListenerCount(string $eventClass)intChỉ đếm các đăng ký trực tiếp.
clearListeners()voidĐặt lại provider.

NextPDF\Event\EventDispatcher (stable, final):

Phương thứcTrả vềMục đích
dispatch(EventInterface $event)EventInterfaceGọ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()ListenerProviderTruy 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ì.

<?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);

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);
}
}
  • Các lớp final. EventDispatcherListenerProviderfinal. 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ém InvalidConfigException. 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. DocumentOutputEvent mang 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 EventAwareDocumentTrait sẽ 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.

Đườ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.

SignatureAppliedEventEncryptionAppliedEvent 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 đó.

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.

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.

Bảng thuật ngữ định nghĩa các thuật ngữ event listener, event dispatcher, listener providerstoppable 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.