Contracts: 41 öffentliche Interfaces (SPI)
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“NextPDF\Contracts ist das öffentliche Service-Provider-Interface (SPI): 41 Interfaces und Enums unter src/Contracts/ mit explizitem @stability-Tag und einem Versprechen zur Abwärtskompatibilität. Erweiterungspakete, Framework-Brücken sowie die Pro- und die Enterprise-Edition programmieren gegen diese Typen, nie gegen konkrete Klassen.
Installation
Abschnitt betitelt „Installation“composer require nextpdf/core:^3Konzeptioneller Überblick
Abschnitt betitelt „Konzeptioneller Überblick“Die Engine trennt zwei Oberflächen voneinander. Konkrete Klassen unter src/Core/, src/Html/ und src/Writer/ tragen kein Kompatibilitätsversprechen. Sie können sich zwischen Minor-Versionen frei ändern. Der Namespace Contracts bildet das Gegenstück: einen kuratierten Satz von Typen, deren Signaturen für die jeweils deklarierte Stabilitätsstufe eingefroren sind. Alles außerhalb der Engine hängt von diesem Namespace ab und von keiner tieferen Ebene. Dazu zählen die Brücken für Laravel, Symfony und CodeIgniter, das compat-tcpdf-Shim, NextPDF Server sowie die Pro- und Enterprise-Edition.
Jeder Contract deklariert in seinem PHPDoc eine von vier Stufen. Bei einem stable-Contract ist in einem Minor- oder Patch-Release keine Breaking Change zulässig. Neue Methoden werden nur mit Default-Implementierungen ergänzt. Ein experimental-Contract darf sich in einem Minor-Release mit einem Deprecation-Hinweis ändern. Ein deprecated-Contract nennt seinen Ersatz. Einige wenige Typen sind reine Contracts, etwa StreamingWriterInterface und CursorInterface. Diese Typen sind veröffentlicht und eingefroren; derzeit wird jedoch noch keine produktionsreife Implementierung ausgeliefert.
Die maßgebliche Liste der Stufen ist docs/extension-points.json (Manifest-Version 3.0.0, 67 veröffentlichte Punkte über Contracts und Event hinweg). Der maschinell prüfbare Test tests/Unit/Contracts/StabilityContractTest.php liest dieses Manifest. Er lässt den Build in fünf Fällen fehlschlagen: erstens, wenn ein gelisteter Typ fehlt; zweitens, wenn die per Reflection ermittelte Typart dem Manifest widerspricht; drittens, wenn ein @stability-PHPDoc-Tag vom Manifest abweicht; viertens, wenn ein Contract unter src/Contracts/ im Manifest fehlt; und fünftens, wenn ein @internal-Typ im Manifest auftaucht. Die Contract-Oberfläche kann dadurch nicht unbemerkt abdriften.
Contracts gehören zu neun Domänen. Jede Domäne hat eine eigene Seite: Dokumenterstellung, Signieren, Barcode-Kodierung, Typografie, Sicherheitsrichtlinie, Extraktion, Observability und Streaming. Die Aufteilung spiegelt wider, wie ein Integrator die Engine übernimmt. Sie hängen vom Dokument-Contract ab, um PDFs zu erzeugen. Sie hängen von den Signier-Contracts ab, um eine Signatur hinzuzufügen. Sie hängen von den Sicherheitsrichtlinien-Contracts ab, um nicht vertrauenswürdiges HTML einzuschränken.
Das Auflösen optionaler Implementierungen folgt in der gesamten Engine einem Muster. Core prüft mit class_exists(), ob eine konkrete Klasse vorhanden ist, und castet sie auf den Contract. LtvManagerInterface und PdfAManagerInterface lösen ihre Pro-Implementierungen auf diese Weise auf. Damit bleibt Core Apache-2.0-lizenziert und ohne harte Abhängigkeit von kommerziellem Code.
API-Oberfläche
Abschnitt betitelt „API-Oberfläche“| Contract | Art | Stabilität | Seit | Domäne |
|---|---|---|---|---|
PdfDocumentInterface | interface | stable | 1.0.0 | document |
DocumentFactoryInterface | interface | stable | 1.7.0 | document |
ResettableService | interface | stable | 1.7.0 | document |
OutputDestination | enum | stable | 1.0.0 | document |
Orientation | enum | stable | 1.0.0 | document |
Alignment | enum | stable | 1.0.0 | document |
SignerInterface | interface | stable | 1.0.0 | signing |
HsmSignerInterface | interface | stable | 1.0.0 | signing |
DeferredSignerInterface | interface | experimental | 3.0.0 | signing |
TimestampProviderInterface | interface | experimental | 3.0.0 | signing |
LtvManagerInterface | interface | stable | 1.10.0 | signing |
CryptoPolicyInterface | interface | stable | 1.9.0 | signing |
Barcode1DEncoderInterface | interface | stable | 1.0.0 | barcode |
Barcode2DEncoderInterface | interface | stable | 1.0.0 | barcode |
BarcodeEncoderInterface | interface | stable | 3.0.0 | barcode |
Gs1DataParserInterface | interface | stable | 1.0.0 | barcode |
FontRegistryInterface | interface | stable | 1.7.0 | typography |
TextPreprocessorInterface | interface | stable | 1.9.0 | typography |
HtmlSecurityPolicyInterface | interface | stable | 3.1.0 | security-policy |
ExternalResourcePolicyInterface | interface | stable | 4.0.0 | security-policy |
InspectorInterface | interface | experimental | 2.2.0 | extraction |
EmbeddingServiceInterface | interface | experimental | 2.1.0 | extraction |
VectorIndexInterface | interface | experimental | 2.1.0 | extraction |
JobNotificationInterface | interface | experimental | 2.2.0 | observability |
SpectrumInterface | interface | experimental | 2.1.0 | observability |
StreamingWriterInterface | interface | experimental | 3.1.0 | streaming |
CursorInterface | interface | experimental | 3.1.0 | streaming |
Die Tabelle listet die primären Contracts auf. Die übrigen Typen — Value-Object-DTOs (TextSegment, TextPreprocessResult), der Sub-Namespace EInvoice, Verhaltens-Enums (DegradationPolicy, UnderlineStyle) und Import-Contracts (ImportedFormObjectInterface, EmbeddedPdfObjectInterface, ChromeRenderResultInterface) — sind auf den Domänenseiten unter Siehe auch dokumentiert. Die vollständige maschinenlesbare Liste steht in docs/extension-points.json und wird nach .ai/contracts-map.md gespiegelt.
Codebeispiel — Schnellstart
Abschnitt betitelt „Codebeispiel — Schnellstart“<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Hello World');$doc->addPage();$doc->setFont('helvetica', '', 24);$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);$doc->save(__DIR__ . '/output/01-hello-world.pdf');Document::createStandalone() liefert ein konkretes Document, das PdfDocumentInterface erfüllt. Verwenden Sie in Ihren eigenen Services das Interface als Type Hint, damit die Engine-Interna austauschbar bleiben.
Codebeispiel — Produktion
Abschnitt betitelt „Codebeispiel — Produktion“<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Core\PdfFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\FontRegistry;
// Created once at process boot in a RoadRunner/Swoole/Octane worker.$fontRegistry = new FontRegistry();$imageRegistry = new ImageRegistry(maxCacheBytes: 50 * 1024 * 1024);$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$factory = PdfFactory::new() ->withCompress(true) ->withDocumentFactory($documentFactory);
for ($request = 1; $request <= 3; $request++) { $doc = $factory->create(); $doc->setTitle("Worker Request #{$request}"); $doc->addPage(); $doc->setFont('helvetica', 'B', 16); $doc->cell(0, 12, "Worker Request #{$request}", newLine: true); $doc->save(__DIR__ . "/output/14-worker-request-{$request}.pdf");}DocumentFactory implementiert DocumentFactoryInterface. Sie hält Singletons von FontRegistryInterface und ImageRegistryInterface über die gesamte Prozesslebensdauer und injiziert sie in jedes kurzlebige Document, sodass ein Worker jede Schriftart über Tausende Requests hinweg nur einmal parst.
Grenzfälle & Fallstricke
Abschnitt betitelt „Grenzfälle & Fallstricke“- Ein reiner Contract-Typ kompiliert, hat aber keine Laufzeitimplementierung. Eine Instanziierung von
StreamingWriterInterfaceoderCursorInterfacepernewkann nicht gelingen, weil noch keine Klasse sie implementiert. Behandeln Sie sie als vorab deklarierte API. - Das
@stability-PHPDoc-Tag ist die maßgebliche Quelle für einen einzelnen Typ.docs/extension-points.jsonist die maßgebliche Quelle für den Satz. Wenn beide einander widersprechen, schlägtStabilityContractTestfehl — verdecken Sie den Widerspruch nicht durch das Bearbeiten einer Seite. experimentalbedeutet in der Praxis nicht instabil; es bedeutet, dass das Kompatibilitätsversprechen schwächer ist. Lesen Sie das Feldbc_promisejedes Contracts in.ai/contracts-map.md, bevor Sie sich darauf festlegen.- Eine
@internal-Klasse ist nie ein Contract, selbst wenn andere Pakete sie technisch referenzieren können. Der Stabilitätstest weist jeden@internal-Typ zurück, der im Manifest auftaucht. - Das Hinzufügen einer Methode zu einem
stable-Interface ist für Implementierer eine Breaking Change, sofern die Methode nicht mit einer Default-Implementierung ausgeliefert wird. Die Engine fügt Funktionalität über neue Interfaces hinzu, nicht durch das Erweitern bestehender.
Performance
Abschnitt betitelt „Performance“Das Programmieren gegen Contracts verursacht keine messbaren Laufzeitkosten: Ein Interface-Type-Hint wird zur Link-Zeit aufgelöst, nicht pro Aufruf. Das performance_budget für das Worker-Beispiel dieser Seite beträgt 1500 ms Wall-Zeit und 64 MB Peak-Speicher über drei Dokumente. Das Schriftarten-Parsing beim ersten Request dominiert dieses Budget. Nachfolgende Requests nutzen den Registry-Cache wieder; die den Contracts zurechenbare Arbeit fällt auf einstellige Millisekunden. Das Kostenmodell ist O(1) pro Contract-Dispatch; die eigentliche Arbeit liegt in der konkreten Implementierung und ist auf der jeweiligen Domänenseite dokumentiert.
Sicherheitshinweise
Abschnitt betitelt „Sicherheitshinweise“Das SPI ist auch eine Sicherheitsgrenze. HtmlSecurityPolicyInterface und ExternalResourcePolicyInterface sind Deny-by-default-Contracts, die einschränken, was nicht vertrauenswürdiges HTML tun kann, bevor es einen Renderer erreicht. CryptoPolicyInterface steuert die Auswahl von Algorithmus und Schlüsselstärke für Signieren und Verschlüsselung. Da es sich um Contracts handelt, kann ein Integrator eine strengere Richtlinie bereitstellen, ohne die Engine zu forken. Legen Sie sich für jede sicherheitsrelevante Richtlinie auf die stable-Stufe fest. Experimentelle Richtlinien-Contracts können zwischen Minor-Releases ihre Form ändern. Die Domänenseiten zu Signieren und Sicherheitsrichtlinie enthalten das vollständige Bedrohungsmodell und die normativen Referenzen.
Konformität
Abschnitt betitelt „Konformität“Dieser Überblick erhebt keinen direkten normativen Anspruch; jede Domänenseite rendert ihren eigenen citations-Block. Die Signier-Contracts bilden ISO 32000-2 §12.8 (digitale Signaturen) und ETSI EN 319 142 (PAdES-Baselines) ab. Der PDF/A-Manager bildet ISO 19005-4 ab. Sehen Sie sich die Seiten zu Signieren, Sicherheitsrichtlinie und Extraktion für die klauselgenauen Konformitätstabellen an.
Kommerzieller Kontext
Abschnitt betitelt „Kommerzieller Kontext“Die Pro- und Enterprise-Edition implementieren den Produktionscode hinter mehreren Core-Contracts: LtvManagerInterface (Langzeitvalidierung), PdfAManagerInterface (PDF/A-Durchsetzung), die Signierer für Hardware Security Module (HSM) und für deferred Signing, die Barcode-Encoder sowie die Embedding- und Vector-Index-Contracts. Core veröffentlicht das Interface und friert es ein; das Premium-Paket liefert die Implementierung. So bleibt die Open-Source-Engine unter Apache-2.0, und kommerzielle Deployments erhalten zugleich ein Drop-in-Upgrade ohne API-Änderung.
Siehe auch
Abschnitt betitelt „Siehe auch“- Contracts / Document — Contracts für PDF-Dokument, Factory und Registry.
- Contracts / Signing — Contracts für Signierer, HSM, Timestamp und LTV.
- Contracts / Security Policy — Contracts für Krypto, HTML und Ressourcenrichtlinie.
- Contracts / Typography — Contracts für Font-Registry und Text-Preprocessing.
- Contracts / Extraction — Contracts für Inspector, PDF/A, Embedding und E-Invoice.
- Core — konkrete Klassen, die diese Contracts erfüllen.
- Event — das Event-SPI-Gegenstück, das zusammen mit
Contractsveröffentlicht wird.