Skip to content

Observe PDF lifecycle events when embedding NextPDF Connect

You can observe and react to PDF lifecycle events — document created, page added, font loaded, signature applied, output produced — without subclassing the document. This is a library-embedding capability, not a Connect tool. The remote Connect transport surface (Model Context Protocol (MCP) / REST / gRPC) exposes no event-listener tool. You observe events only when you host the engine in-process and wire a dispatcher. This page draws that boundary and shows the in-process pattern clearly, so callers do not expect a remote hook.

Terminal window
composer require nextpdf/server

Use this pattern when your application embeds the engine and calls it directly in PHP, such as from a custom server host. Over a remote transport, observe the system at the transport boundary with telemetry instead.

The engine fires events through a PSR-14-style dispatcher. You create a listener provider and dispatcher, register listeners by event class, and then attach the dispatcher to a document. From there, events fire automatically as the document is built. When no dispatcher is attached, the event system adds zero cost because every dispatch point is a null check. Classes resolve through the autoload class→file mapping (PSR-4 §3), and all sample code declares strict types and follows the coding standard (PSR-12 §2.1).

There is no Connect tool for event hooks. The tool catalog is the catalog of record, and it lists none. The in-process surface is the engine’s event classes (DocumentCreatedEvent, PageAddedEvent, FontLoadedEvent, SignatureAppliedEvent, EncryptionAppliedEvent, DocumentOutputEvent) together with the listener provider and dispatcher. The tools available over a transport depend on the installed tier, and event hooks are never among them.

<?php
declare(strict_types=1);
use NextPDF\Core\Document;
use NextPDF\Event\EventDispatcher;
use NextPDF\Event\ListenerProvider;
use NextPDF\Event\Document\DocumentCreatedEvent;
use NextPDF\Event\Document\PageAddedEvent;
$provider = new ListenerProvider();
$dispatcher = new EventDispatcher($provider);
$provider->addListener(
DocumentCreatedEvent::class,
static function (DocumentCreatedEvent $event): void {
// react to creation
},
);
$provider->addListener(
PageAddedEvent::class,
static function (PageAddedEvent $event): void {
// react to a new page: $event->pageIndex
},
);
$pdf = Document::createStandalone();
$pdf->setEventDispatcher($dispatcher);
$pdf->addPage()->setFont('Helvetica', '', 12)->cell(0, 10, 'Hello')->save('/tmp/out.pdf');

Use these common in-process patterns:

  • Audit logging. Register a listener on the base event class with a low priority so that it always runs last, and record the event name and context.
  • License/limit enforcement. Listen on PageAddedEvent with a high priority. Past a page cap, stop propagation and raise a typed exception.
  • Post-processing. Listen on DocumentOutputEvent, and then transform the PDF bytes before they are returned.
  • Security monitoring. Listen on SignatureAppliedEvent / EncryptionAppliedEvent, and record the level/algorithm and permission flags to an audit log.

Priority guide: ≥1000 for security/limit checks, 0 for normal listeners, and ≤−1000 for audit/telemetry.

  • Not available over a remote transport. A remote MCP/REST/gRPC client cannot register a listener, so do not document or expect a remote hook.
  • Zero-overhead only without a dispatcher. Attaching a dispatcher adds the cost of its listeners, so keep hot-path listeners cheap.
  • Propagation control. Stopping propagation prevents later listeners from running, so order by priority deliberately.

With no dispatcher, the cost is zero. With listeners, the cost is the sum of their work. The profile is structural for produced documents.

Listeners can see signing and encryption events, so treat every audit sink as sensitive. A post-processing listener that mutates output bytes is a trust point, so keep it minimal and reviewed.

StatementSpecClausereference_id
Event classes resolve via the autoload mapping.PSR-4§3
Sample code declares strict types per the standard.PSR-12§2.1

Not applicable — the event system is Core, and it is not part of the remote Connect tool surface.

TransportAvailableNotes
MCP (stdio)NoNo event-listener tool is exposed.
RESTNoNo event-listener endpoint.
gRPCNoNo event-listener RPC.
In-process (library embed)YesThe PSR-14 dispatcher pattern above.

For remote deployments, observe at the transport boundary with telemetry instead of expecting engine event hooks.

Not applicable — there is no Connect tool here, so the confirmation gate is not involved. The host must guard any in-process post-processing that writes files.

Not applicable — no tool call is made. (For tool-call gating see output-approval.)