コンテンツにスキップ
getnextpdf.com

一つのエンジン、あらゆるフレームワーク

Spec: PSR-11 Container, §1.1.2Spec: PSR-4 Autoloader, §3

成長する PHP 環境の多くは、複数のフレームワークを抱えるに至ります。NextPDF は、それぞれのフレームワークに、その流儀のままで応える一つの PDF エンジンです。LaravelSymfonyCodeIgniter 向けの慣用的なブリッジに加え、いずれのフレームワークでも動かないコードのためのスタンドアロン経路を備えています。文書モデルは共有されます。変わるのは、それを呼び出す方法だけです。

スタックごとに異なる PDF ライブラリは、静かな税です。それぞれが独自の癖、独自のフォント処理、有効とは何かについての独自の考えを持っています。Laravel のサービスから正しくレンダリングされる請求書が、Symfony のワーカーからは微妙に異なってレンダリングされるかもしれません。別のライブラリがそれを描いたからです。こうなると、あなたのアーカイブ目標も、署名の配置も、アクセシビリティタグも、どのチームが文書を出荷したかに依存することになります。バグ報告には「PDF が間違っている」とあり、その答えは三つのエンジンのどれが生成したかに依存するのです。

一つのエンジンに標準化すれば、その面が一つに収束します。PDF/A プロファイルを決める場所は一つ、認証すべきフォントパイプラインは一つ、信頼すべきバリデーターは一つになります。たまたまどのフレームワークにいるかは、文書が正しいかどうかを左右する変数ではなくなります。

  • コアエンジンはフレームワーク非依存です。 nextpdf/core は、HTTP、ルーティング、コンテナの配線について何も知りません。これは PDF 2.0 エンジンであり、それ以上の何物でもありません。
  • 各ブリッジは適応するのであって、再実装しません。 LaravelSymfonyCodeIgniter の各パッケージは、同じエンジンの上に、ファサードまたはファクトリ、HTTP レスポンスヘルパー、そしてキュー型または非同期の生成経路を提供します。
  • ブリッジが従うのは、あなたのフレームワークであって、あなたの文書ではありません。 それはエンジンの呼び出し方を変えるのであって、エンジンが生成できるものは変えません。
  • スタンドアロンは常に利用できます。 CLI ツール、デーモン、ライブラリには、ブリッジする元となるフレームワークがありません。文書を直接構築します。
  • 一つの文書モデルが四つすべてにわたって通用します。 同じ値オブジェクト、列挙型、出力契約がどこにでも現れるため、文書は呼び出し箇所の間を変わらずに移動します。

このアーキテクチャは意図的な分割です。エンジンが資産であり、ブリッジは一つのフレームワークの流儀を話す薄いアダプターです。ブリッジは、標準のオートロード(Spec: PSR-4 Autoloader, §3)を通じて共有コアの上に小さな名前空間を登録し、コンテナ契約(Spec: PSR-11 Container, §1.1.2)を通じて文書を返します。その契約こそが、ここでの静かな立役者です。同じ識別子の二つの解決が異なるインスタンスを返すことを許容します。これはまさに、解析済みフォントレジストリと画像キャッシュをプロセス全体のシングルトンとして保ちながら、ブリッジがリクエストごとに新しい使い捨ての文書を渡す仕組みそのものです。長命なワーカー――OctaneRoadRunnerSwooleMessenger――は、リクエスト間の状態漏れなしに、構造上、フォント解析の償却を享受します。

四つの流儀は、表面でのみ異なります。

  1. Core enginenextpdf/core — the framework-agnostic PDF 2.0 engine; the single shared document model, value objects, and output contract.
  2. Laravel bridgenextpdf/laravel — auto-discovered provider, a Pdf facade, a PdfResponse helper, and a queued GeneratePdfJob.
  3. Symfony bridgenextpdf/symfony — an auto-registered bundle, an injectable PdfFactory, a PdfResponse, and an optional Messenger handler.
  4. CodeIgniter bridgenextpdf/codeigniter — a service and pdf() helper, a Pdf library over a disposable Document, and a PdfResponse.
  5. StandaloneNo framework to bridge from — construct a Document directly in a CLI tool, daemon, or library.
一つのフレームワーク非依存のコアエンジンに、四つの慣用的なサーフェスを通じて到達します。Laravel のファサード、注入された Symfony のファクトリ、CodeIgniter のサービス、あるいは直接構築されたスタンドアロンの文書――いずれも同じ使い捨ての Document モデルを返します。

図を左から右へ読むと、そこにある教訓は対称性です。あらゆるサーフェスが同じ Document に解決されます。Laravel のファサード、Symfony のファクトリ、CodeIgniter のサービス、そしてスタンドアロンのコンストラクタは、一つの部屋への四つの扉です。

同じ三行の意図を、それぞれの流儀で表現したものです。文書を構築する本体――ページ、フォント、セル、署名、準拠――は四つすべてで同一です。同じエンジンだからです。

<?php
declare(strict_types=1);
// Laravel — resolve a fresh document from the container.
use NextPDF\Contracts\PdfDocumentInterface;
$document = app(PdfDocumentInterface::class);
// Symfony — inject the factory, then ask it for a document.
use NextPDF\Symfony\Service\PdfFactory;
$document = $factory->create(); // PdfFactory injected into your service
// CodeIgniter — pull it from the Services layer.
use NextPDF\CodeIgniter\Config\Services;
$document = Services::pdfDocument();
// Standalone — no framework; construct it directly.
use NextPDF\Core\Document;
$document = Document::createStandalone();
// From here, the code is identical regardless of how $document arrived.
$document->addPage();
$document->cell(0, 10, 'One engine, every framework', newLine: true);
$bytes = $document->getPdfData();

最初の数行だけが唯一の違いです。それ以降はすべて可搬です。文書構築サービスを Symfony からスタンドアロンのワーカーへ移しても、レンダリングのコードは変わりません。それが依存する契約が変わらないからです。

よくある思い込みは、フレームワークブリッジが機能を解放するというものです――つまり、エンジンを直接呼び出すのではなく nextpdf/laravel をインストールしたから、長期署名検証や構造化電子請求が手に入る、というものです。そうではありません。ブリッジは呼び出し箇所を変えるのであって、エンジンの範囲を変えることは決してありません。PDF/A 出力や PAdES ベースライン署名のようなコア機能はオープンソースであり、あらゆるサーフェスに届きます。上位機能はエディションによって解放され、その後はあらゆるブリッジまたはスタンドアロン経路から等しく利用できます。フレームワーク統合の選択は、機能セットの選択ではありません。

裏返しの誤解は、「一つのエンジン」がすべての文書に対する一つのレンダリング経路を意味するに違いない、というものです。そうではありません。プロセス内エンジンは PDF を直接レンダリングします。文書が本当にブラウザー級のレイアウトエンジンを必要とするときは、レンダラーパッケージがそれを扱います。レンダリングと呼び出しは別個の軸です――統合の意思決定ガイドが、それらを対応づける場所です。

ブリッジは、エンジンがレンダリングできる範囲を広げません。それが誠実な限界であり、そしてそれこそが要点です。能力はコアとティアにあるのであって、それを通じて到達するアダプターにあるのではありません。

Framework bridges over one engine — edition availability
EditionAvailability
Core

あらゆるブリッジ(LaravelSymfonyCodeIgniter)とスタンドアロン経路は Apache-2.0 であり、Core に対して機能します。これらはエンジンを適応または公開します。 機能をゲートすることはなく、エンジンが生成できるものを変えることもありません。

Pro

長期署名検証(PAdES B-LT および B-LTA)のような上位機能はエディションによって解放され、その後はあらゆるブリッジまたはスタンドアロンを通じて同一に到達します――フレームワークを切り替えることによってではありません。PDF/A アーカイブ出力と PAdES ベースライン署名(B-B および B-T)はすでに Core にあり、 あらゆるサーフェスを通じて同じように利用できます。

Enterprise

構造化電子請求(EN 16931)とより深いコンプライアンスツールもまたエディションの機能であり、同様にどのサーフェスがエンジンを呼び出しても同じです。一方で準拠検証そのものは Core に同梱されています。

さらに二つの境界を明確に述べておく価値があります。第一に、各ブリッジは自らのフレームワークの現行メジャーバージョンを追従します。LaravelSymfonyCodeIgniter はそれぞれサポート範囲を固定するため、「あらゆるフレームワーク」が意味するのは各々のサポート対象バージョンであって、過去のすべてのリリースではありません。各パッケージの API については、そのパッケージ自身のドキュメントを正典として扱ってください。第二に、ブリッジはフレームワークアダプターであって、レンダリングバックエンドではありません。文書が完全なブラウザーレイアウトエンジンを必要とするなら、それはどのフレームワークがエンジンを呼び出したかとは独立したレンダラーの選択です。

  • 統合の意思決定ガイド ――標準化ではなく意思決定が必要なときの、ユースケースからパッケージへの地図。レンダラーや Connect サービスサーフェスを含みます。
  • オープンコア、ロックインなし ――なぜエンジンが資産でブリッジが薄いのか、だから標準化があなたを閉じ込めない理由。
  • HTML パイプライン ――プロセス内エンジンがカバーする範囲。だからブラウザーレンダラーが別個の問題となる場面がわかります。
  • PHP 8.4 の基盤 ――あらゆるブリッジとスタンドアロン経路が共有するランタイムの下限。
  • コアエンジン ――nextpdf/core。あらゆるブリッジとスタンドアロン経路が拠って立つ、フレームワーク非依存の PDF 2.0 エンジン。
  • フレームワークブリッジ ――エンジンをフレームワークの流儀――ファサード、ファクトリ、レスポンス、キュー型ジョブ――に適応させる統合パッケージ(LaravelSymfonyCodeIgniter)。その機能を変えることはありません。
  • スタンドアロン経路 ――フレームワークなしで、Document を自分で構築してコアエンジンを直接使うこと。CLI ツール、デーモン、ライブラリのための経路。
  • 使い捨て文書 ――一度きりの Document 契約。構築し、出力し、破棄します。コンテナの各解決は新しいものを返すため、長命なワーカーでもリクエスト間に状態が漏れません。
  • PAdES ――PDF Advanced Electronic Signatures。PDF 署名のための ETSI プロファイルファミリー。ベースライン署名(B-B および B-T)は Core にあり、長期検証(B-LT および B-LTA)は上位エディションの機能です。いずれもあらゆるサーフェスを通じて到達でき、署名のページで詳しく扱っています。