Перейти к содержимому

ValueObjects: доменные примитивы и единицы измерения

Модуль ValueObjects предоставляет неизменяемые геометрические примитивы, которые используются во всём движке: PageSize, Dimension, Position, Margin и перечисление Unit. Каждый из них — класс final readonly. Экземпляр можно свободно использовать совместно; каждое преобразование возвращает новый экземпляр.

Окно терминала
composer require nextpdf/core:^3

Все четыре объекта-значения объявлены как final readonly. Они хранят значения типа float и не содержат изменяющих методов; методы преобразования создают новый экземпляр с именованными аргументами. Их можно кэшировать, передавать между документами и совместно использовать в разных воркерах без защитного копирования.

PageSize хранит ширину, высоту (в пунктах; 1 пт = 1/72 дюйма) и имя. Статические фабрики охватывают серию A стандарта International Organization for Standardization (ISO) 216 (A0A6), серию B ISO 216 (B0B5) и североамериканские форматы (Letter, Legal, Tabloid). Размеры серий A/B соответствуют серии форматов обрезанной бумаги, определённой стандартом ISO 216. fromName() распознаёт имена без учёта регистра и выбрасывает PageLayoutException, если имя неизвестно. landscape() и portrait() возвращают вариант в нужной ориентации или self, если страница уже в такой ориентации. toDimension() преобразует размер страницы в Dimension в пунктах.

Dimension хранит ширину, высоту и Unit. Фабрики (fromMillimeters(), fromPoints(), fromInches()) создают габарит в выбранной единице измерения. toPoints() и toMillimeters() преобразуют единицы измерения; toPoints() возвращает self, если габарит уже выражен в пунктах. withWidth() и withHeight() возвращают копию с изменённым размером. Преобразование использует точные коэффициенты: 72/25.4 пункта на миллиметр, 72/2.54 на сантиметр и 72 на дюйм.

Position — двумерная точка в пользовательском пространстве Portable Document Format (PDF) (x, y). origin() возвращает (0, 0). translate(dx, dy) возвращает смещённую копию. withX() / withY() возвращают копию с заменой одной координаты.

Margin содержит top, right, bottom и left. Фабрики: uniform() (одинаковое значение со всех сторон), symmetric(vertical, horizontal) и zero().

Unit — перечисление со строковым значением: Point (pt), Millimeter (mm), Centimeter (cm) и Inch (in). toPointFactor() возвращает множитель для перевода в пункты.

СимволТипКлючевые члены
NextPDF\ValueObjects\PageSizeкласс final readonly$width, $height, $name; фабрики A0A6, B0B5, Letter, Legal, Tabloid; fromName(), landscape(), portrait(), toDimension()
NextPDF\ValueObjects\Dimensionкласс final readonly$width, $height, $unit; fromMillimeters(), fromPoints(), fromInches(), toPoints(), toMillimeters(), withWidth(), withHeight()
NextPDF\ValueObjects\Positionкласс final readonly$x, $y; origin(), translate(), withX(), withY()
NextPDF\ValueObjects\Marginкласс final readonly$top, $right, $bottom, $left; uniform(), symmetric(), zero()
NextPDF\ValueObjects\Unitстроковое перечислениеPoint, Millimeter, Centimeter, Inch; toPointFactor()

Используйте фабрики для создания геометрических примитивов.

<?php
declare(strict_types=1);
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
use NextPDF\ValueObjects\Position;
$page = PageSize::A4(); // 595.276 x 841.890 pt
$margin = Margin::uniform(18.0); // 18 pt all sides
$origin = Position::origin()->translate(72.0, 72.0); // 1 inch in from corner

Преобразуйте единицы измерения, определите ориентацию и передайте поля в конфигурацию.

<?php
declare(strict_types=1);
use NextPDF\Core\Config;
use NextPDF\ValueObjects\Dimension;
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
// A label sized in millimeters, resolved to points for the engine.
$label = Dimension::fromMillimeters(width: 100.0, height: 150.0)->toPoints();
$page = PageSize::A4()->landscape(); // swap to width >= height
$margin = Margin::symmetric(vertical: 20.0, horizontal: 15.0);
$config = (new Config())
->withPageSize($page)
->withMargins($margin);
// $label->width / $label->height are now in points for downstream layout.
  • Все габариты используют пункты, если вы не передаёте Dimension с явно указанной Unit. Поля Config по умолчанию также используют пункты.
  • PageSize::landscape() / portrait() возвращают тот же экземпляр, если ориентация уже совпадает; выделение памяти не происходит, а идентичность сохраняется.
  • PageSize::fromName() игнорирует регистр, но принимает только имена, для которых есть именованные фабрики. Неизвестное имя вызывает PageLayoutException, а не подставляет размер по умолчанию.
  • Dimension::toPoints() возвращает self, если единица измерения уже Point; не рассчитывайте на новый объект.
  • Эти объекты хранят необработанные значения типа float и не выполняют проверку диапазона. При создании они допускают отрицательные или нулевые размеры. Корректность геометрии обеспечивают слои макета и записи, а не сами объекты.
  • Преобразования с плавающей запятой используют точные рациональные коэффициенты (72/25.4, 72/2.54); округляйте только на границе представления, чтобы воспроизводимый вывод оставался стабильным.

Каждый объект-значение — плоская readonly-структура из чисел с плавающей запятой. Создание и каждое преобразование требуют одного выделения памяти со сложностью O(1) без глубокого копирования, поскольку вложенного изменяемого состояния нет. Экземпляр можно совместно использовать в разных документах без дополнительных затрат. Стандартный performance_budget для этой справочной страницы — wall_ms: 1500, peak_mb: 64.

Эти объекты-значения не выполняют операций input/output (I/O), не содержат пользовательских строк, кроме имени размера страницы, и не хранят дескрипторы внешних ресурсов, поэтому они не создают прямой поверхности атаки. PageSize::fromName() отклоняет неизвестные входные данные, выбрасывая исключение вместо молчаливого отката, поэтому некорректная конфигурация завершается явной ошибкой, а не порождает неожиданную геометрию страницы.

СтандартПунктТема
ISO 216:2007Серии A / BРазмеры обрезанной бумаги для фабрик A* / B* (изложено своими словами; текст ISO не цитируется, фрагмент не закреплён)

Размеры фабрик A и B соответствуют обрезанным форматам ISO 216, выраженным в пунктах. Североамериканские форматы (Letter, Legal, Tabloid) — фактические отраслевые форматы, не основанные на стандарте ISO. Ссылка на ISO изложена своими словами в соответствии с политикой цитирования сайта. Дословный фрагмент не закреплён.

  • /modules/core/config/Config использует PageSize и Margin
  • /modules/core/layout/ — потребители этих примитивов в макете
  • /modules/core/graphics/Position в координатном пространстве рисования
  • /modules/core/contracts/Orientation вместе с PageSize
  • /modules/core/exception/PageLayoutException из fromName()