コンテンツにスキップ

PHP 8.4 の基盤

Spec: ISO 32000-2, §7.5.2 Evidence: Code-backed PHP 制約: ≥8.4 <9.0

NextPDF は PHP 8.4 を必要とします。このページでは、エンジンが実際に依存している 8.4 の言語機能、なぜそのバージョンが単なる推奨ではなく厳格な下限なのか、そして別系統のダウングレードビルドが、読み手が確認するコードベースを弱めることなく、古いランタイムで動作させる選択肢をどのように維持しているのかを解説します。

PDF エンジンは、曖昧な入力をバイト単位で正確なファイル形式へ変換します。PDF は長年確立されてきた形式で、固定的なルールが明確にあり、誤った推測の代償が大きい、厳格な形式です。エンジンを書く言語は、そうした推測が捕捉されるのか、未検査のまま通過するのかを最初に左右する場所です。バージョン下限は、制限そのものを目的にしたものではありません。これを下回ると、エンジンは設計の他の部分が依存する型保証をもはや成立させられなくなります。

その下限が曖昧だと、二つの代償が生じます。コードベースは、本来のロジックを覆い隠す互換性シムで埋め尽くされます。型システムも構造を支える役割を果たせなくなりますが、それはまさにドキュメントパイプラインが失うわけにはいかない性質です。

  • コアパッケージは "php": ">=8.4 <9.0" を宣言します。これは composer.json で検証された実際の制約であり、ドキュメント上の願望ではありません。
  • 8.4 が下限であるのは、エンジンが 8.4(および最近の 8.x)の言語機能を構造上の保証として使っているためです。具体的には、非対称可視性、振る舞いを持つバックド enum、型付きクラス定数、readonly な状態、そして公開 API における第一級の名前付き引数です。
  • PHP 8.1〜8.3 での実行は、別系統のダウングレードビルド(バックポート)を通じて引き続き可能です。これはビルドツールであり、ランタイム依存ではありません。コアリポジトリで読むコードを変更することはありません。
  • 上限の <9.0 は意図的です。新しいメジャー PHP リリースは、前提とせず、検証対象として扱います。

下限は、コードが実際に何をしているかによって決まります。そのため、誠実に説明するなら、機能を抽象的に列挙するのではなく、コードの中で示す必要があります。

非対称可視性を使うと、すべてのフィールドに手書きのゲッターを用意しなくても、状態を公開的に読み取り可能にしつつ、書き込みは非公開に限定できます。レンダリングコンテキストはこれを直接使用しています。

declare(strict_types=1);
final class RenderingContext
{
// Readable everywhere, writable only inside the class.
public private(set) float $x = 0.0;
public private(set) float $y = 0.0;
public private(set) int $currentPageIndex = -1;
public private(set) string $currentContentStream = '';
}

このたった一つの言語機能で、外部からの偶発的な変更というカテゴリ全体を取り除けます。エンジンの外部からカーソルを動かすことはできません。この保証は、レビュアーが覚えておくべき慣習ではなく、ランタイムによって強制されます。

振る舞いを持つバックド enum は、散在するブール値フラグや文字列定数を、自分自身についての問いにも答えられる単一の型付き値へ置き換えます。ドキュメント適合性の判別子はバックド enum であり、そのメソッドが仕様レベルの結果を決定します。

declare(strict_types=1);
enum ConformanceMode: string
{
case Plain = 'plain';
case PdfUa2 = 'pdfua2';
case PdfA4 = 'pdfa4';
case PdfA4f = 'pdfa4f';
public function isTagged(): bool
{
return match ($this) {
self::Plain => false,
default => true,
};
}
/** @return 2|3|4|null */
public function pdfaPart(): ?int
{
return match ($this) {
self::PdfA4, self::PdfA4f => 4,
default => null,
};
}
}

この enum は、「このドキュメントは仕様タグ付きか?」そして「どの ISO パートが適用されるか?」という問いに対する唯一の信頼できる情報源です。これらの問いを緩いブール値で表現していた場合、複数の箇所が一貫しない答えを返す可能性がありました。

型付きクラス定数は、定数も型契約の一部にします。HTML エンジンの厳格な上限は、型付き定数として宣言されています。

private const int MAX_NESTING_DEPTH = 100;
private const int MAX_ELEMENT_COUNT = 50_000;

名前付き引数は、内部的な小技ではなく、公開 API の表面の一部です。サンプルプログラムでは、読者がそのまま複製することを想定した呼び出し箇所で、これらを渡しています。

$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);

これらは、新しい構文を飾りとして使っているわけではありません。それぞれが、本来ならレビュアーが手作業で守らせる必要のある慣習を、ランタイムが強制する性質へと変換します。

このページは Evidence: Code-backed です。上記のすべての主張は、機能一覧ではなく、コアリポジトリ内のファイルに対応しています。

  • バージョン制約は、コアの composer.json 内の require.php の値 ">=8.4 <9.0" です。
  • 非対称可視性の例は、src/Core/RenderingContext.php で実際に使われている宣言スタイル(public private(set) フィールド)です。
  • enum の例は src/Conformance/ConformanceMode.php を反映しており、match ベースのメソッドが適合性の判断を駆動する、バックド enum … : string です。
  • 型付き定数は src/Html/HtmlParser.php にあります(private const int MAX_NESTING_DEPTHMAX_ELEMENT_COUNT)。
  • 名前付き引数の呼び出しは、同梱の examples/ プログラムから取られています。

下限には標準規格の側面もあります。エンジンの役割は、次の仕様に適合するファイルを出力することです。 Spec: ISO 32000-2, §7.5.2 。 適合する PDF 2.0 のライターは、ドキュメントのバージョンを 2.0 として、ファイルヘッダーまたはカタログ内で宣言しなければなりません。これほど精密な要件を満たすには、 ライターの土台となる言語が、不整合な状態をそもそも構築しにくくしている方が、 はるかに容易です。バージョン下限と形式の厳格さは、歩調を合わせています。

最小限の正しいプログラムでも、すでにその下限を前提にしています。これは PHP 8.4 上で動作し、名前付き引数を使用し、適合するファイルを生成します。

<?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__ . '/hello.pdf');

ここには特殊なものは何もありません。重要なのは、エンジン内部を信頼できるものにしているのと同じ厳格な型付け、enum、非対称可視性の仕組みが、この 5 行のプログラムの下ですでに動作していることです。これを有効にするために、明示的な選択は必要ありません。

最もよくある読み違いは、「PHP 8.4 を必要とする」が「8.4 にアップグレードしない限り動作しない」を意味する、というものです。これは、コアソースが 8.4 を対象としているという意味です。PHP 8.1〜8.3 に固定されているチームのために、別系統のダウングレードビルドが用意されています。

そのビルドが何であるかを正確に捉えることが重要です。これは、8.4 のソースを古い構文の出力へ変換する、Rector ベースのダウングレードパイプラインです。これはビルドインフラであり、アプリケーションの依存関係に追加するランタイムライブラリではありません。また、並行して存在する型付けの弱いコードベースを持ち込むものでもありません。これらのページでレビューされるコードと、出荷されるコードは同一のコードです。バックポートはそれに適用される変換であり、それの代替ではありません。

このページでは、なぜ 8.4 が下限なのか、そしてバックポートが 何を 維持するのかを解説します。ダウングレードパイプラインの実行方法、サポートされる対象バージョン、運用上の注意点は解説しません。それらは、バックポートビルド自身のドキュメントに属します。そのツールの内部パッケージ構成は、ここでは対象外です。示されている機能の使用例は、エンジンのスタイルを例示するものです。コードベースが使用するすべての 8.x 機能の完全な一覧ではありません。正確な API は、この解説ではなくリファレンスによって定義されます。バージョン制約は、このページのレビュー日時点で正確です。権威ある値は、常にコアの composer.json 内の require ブロックです。

エディションは、言語の下限には関係しません。すべてのエディションは、同じ PHP 8.4 のソースからビルドされます。

PHP 8.4 source floor — edition availability
Edition Availability
Core Core は PHP 8.4 に対して記述されています。
Pro Pro は同じ 8.4 のソース下限の上に構築されています。
Enterprise Enterprise は同じ 8.4 のソース下限の上に構築されています。
  • バージョン下限 — コアソースが対象とする最小の PHP バージョン(>=8.4)。これを下回ると、エンジンの型保証を表現できません。
  • 非対称可視性 — プロパティを公開的に読み取れるようにしながら、書き込みはより狭いスコープからのみ可能にする PHP 8.4 の機能(public private(set))。
  • バックド enum — ケースがスカラー値を持ち、振る舞い(メソッド)を備えられる PHP の enum。ここでは唯一の型付き信頼情報源として使用されています。
  • バックポート — 8.4 のソースを、古い PHP で実行可能な出力へ変換する、別系統の Rector ベースのダウングレードビルド。ビルドツールであり、ランタイム依存ではありません。
  • 適合モード — ドキュメントがどの ISO 適合性契約を満たさなければならないかを示す、エンジンの型付き判別子。