База PHP 8.4
Spec: ISO 32000-2, §7.5.2 ISO 32000-2 §7.5.2 Evidence: Code-backed Ограничение PHP: ≥8.4 <9.0
NextPDF требует PHP 8.4. На этой странице объясняется, на какие возможности языка 8.4 опирается движок, почему эта версия является жёсткой нижней границей, а не мягкой рекомендацией, и как отдельная backport-сборка сохраняет работу на более старой среде выполнения, не ослабляя код, который вы читаете.
Почему это важно
Заголовок раздела «Почему это важно»PDF-движок превращает неоднозначные входные данные в побайтово точный формат файла. PDF — давно устоявшийся формат с жёсткими фиксированными правилами, и он достаточно строг, чтобы ошибочная догадка обходилась дорого. Язык, на котором написан движок, — первое место, где такие догадки либо перехватываются, либо проходят без проверки. Нижняя граница версии — не ограничение ради ограничения. Это черта, ниже которой движок уже не может давать гарантии типов, от которых зависит вся остальная архитектура.
Если эту границу размыть, возникают две издержки. Кодовая база обрастает прослойками совместимости, которые скрывают реальную логику. Система типов тоже перестаёт быть несущей, а именно это свойство конвейер обработки документов не может позволить себе потерять.
Если коротко
Заголовок раздела «Если коротко»- Основной пакет объявляет
"php": ">=8.4 <9.0". Это и есть реальное ограничение, проверяемое вcomposer.json, а не пожелание из документации. - 8.4 — это нижняя граница, потому что движок использует возможности языка 8.4 (и недавних версий 8.x) как структурные гарантии: асимметричную видимость, перечисления со значениями и поведением, типизированные константы классов, readonly-состояние и именованные аргументы первого класса в публичном API.
- Запуск на PHP 8.1–8.3 по-прежнему возможен через отдельную backport-сборку. Это инструмент сборки, а не зависимость времени выполнения. Он не меняет код, который вы читаете в основном репозитории.
- Верхняя граница
<9.0выбрана намеренно: новый мажорный выпуск PHP рассматривается как то, что нужно проверить, а не принять на веру.
Как NextPDF подходит к этому
Заголовок раздела «Как NextPDF подходит к этому»Нижнюю границу задаёт то, что делает код. Поэтому честнее объяснять её через реальные фрагменты, а не отвлечённый список возможностей.
Асимметричная видимость позволяет публично читать состояние, но записывать его только из приватной области, без вручную написанного геттера для каждого поля. Контекст отрисовки использует её напрямую:
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 = '';}Уже эта возможность языка устраняет целую категорию случайных внешних изменений. Курсор нельзя сдвинуть извне движка. Эту гарантию обеспечивает среда выполнения, а не соглашение, о котором должны помнить ревьюеры.
Перечисления со значениями и поведением заменяют разрозненные булевы флаги и строковые константы одним типизированным значением, которое само отвечает на вопросы о себе. Дискриминатор соответствия документа — перечисление со значениями, методы которого определяют исходы на уровне спецификации:
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, }; }}Это перечисление — единственный источник истины для вопросов “помечен ли этот документ согласно спецификации?” и “какая часть 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 . Каждое утверждение выше соответствует файлу в основном репозитории, а не абстрактному списку возможностей:
- Ограничение версии — это значение
require.php">=8.4 <9.0"в основномcomposer.json. - Пример асимметричной видимости — реальный стиль объявления в
src/Core/RenderingContext.php(поляpublic private(set)). - Пример перечисления отражает
src/Conformance/ConformanceMode.php— перечисление со значениямиenum … : string, методы которого на основеmatchуправляют решениями о соответствии. - Типизированные константы находятся в
src/Html/HtmlParser.php(private const int MAX_NESTING_DEPTH,MAX_ELEMENT_COUNT). - Вызов с именованным аргументом взят из поставляемых программ
examples/.
У этой границы есть и связанное со стандартами измерение. Задача движка — выдавать файлы, соответствующие Spec: ISO 32000-2, §7.5.2 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');Здесь нет ничего экзотического. Суть в том, что тот же механизм строгой типизации, перечислений и асимметричной видимости, который делает внутреннее устройство движка надёжным, уже работает под этой программой из пяти строк. Вы не подключаете его явно.
Распространённое заблуждение
Заголовок раздела «Распространённое заблуждение»Самое частое неверное прочтение состоит в том, что “требует PHP 8.4” означает “не будет работать, пока вы не обновитесь до 8.4”. Это означает, что основной исходный код ориентирован на 8.4. Для команд, привязанных к PHP 8.1–8.3, существует отдельная backport-сборка.
Важно точно понимать, чем является эта сборка. Это конвейер понижения версии на основе Rector, который преобразует исходный код 8.4 в вывод со старым синтаксисом. Это инфраструктура сборки, а не библиотека времени выполнения, которую вы добавляете в зависимости своего приложения. Она не создаёт параллельную кодовую базу с более слабой типизацией. Код, разбираемый на этих страницах, и поставляемый код — один и тот же код. Backport — применяемое к нему преобразование, а не альтернатива ему.
Границы и пределы
Заголовок раздела «Границы и пределы»Эта страница объясняет, почему 8.4 является нижней границей и что сохраняет backport. Она не описывает, как запускать конвейер понижения версии, какие целевые версии он поддерживает и какие у него эксплуатационные оговорки. Это относится к собственной документации backport-сборки. Внутренняя структура пакетов этого инструментария здесь вне рамок. Показанные случаи использования возможностей иллюстрируют стиль движка. Это не полный перечень всех возможностей 8.x, которые использует кодовая база. Точные API определяет справочник, а не это объяснение. Ограничение версии актуально на дату проверки этой страницы. Авторитетным значением всегда является блок require в основном composer.json.
Редакция никак не влияет на языковую границу. Каждая редакция собирается из одного и того же исходного кода на PHP 8.4:
| Edition | Availability |
|---|---|
| Core | Core написан под PHP 8.4. |
| Pro | Pro построен на той же нижней границе исходного кода 8.4. |
| Enterprise | Enterprise построен на той же нижней границе исходного кода 8.4. |
Связанные документы
Заголовок раздела «Связанные документы»- Строгая типизация повсюду — как дисциплина статического анализа превращает языковую границу в гарантию.
- Модель конвейера — архитектура, которую эти возможности языка удерживают вместе.
- Философия проектирования NextPDF — почему движок предпочитает явные контракты, обеспечиваемые во время выполнения.
Глоссарий
Заголовок раздела «Глоссарий»- Нижняя граница версии — минимальная версия PHP, на которую ориентирован основной исходный код (
>=8.4). Ниже неё гарантии типов движка невозможно выразить. - Асимметричная видимость — возможность PHP 8.4, позволяющая свойству быть публично читаемым, но доступным для записи только из более узкой области (
public private(set)). - Перечисление со значениями (backed enum) — перечисление PHP, варианты которого имеют скалярные значения и которое может нести поведение (методы); здесь используется как единственный типизированный источник истины.
- Backport — отдельная backport-сборка на основе Rector, которая преобразует исходный код 8.4 в вывод, исполняемый на более старом PHP. Инструмент сборки, а не зависимость времени выполнения.
- Режим соответствия — типизированный дискриминатор движка, определяющий, какому контракту соответствия ISO должен удовлетворять документ.