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

Миграция с FPDF на NextPDF

Это руководство помогает перенести кодовую базу на основе FPDF на ядро NextPDF. FPDF — одна из самых широко используемых устаревших PHP-библиотек формата Portable Document Format (PDF), а её поверхность отрисовки — AddPage, SetFont, Cell, MultiCell, Write, Text, Image, Output, управляемые ручным курсором x/y, — чисто соответствует собственному cell/text-API NextPDF, потому что низкоуровневые методы отрисовки NextPDF происходят из той же линии FPDF/TCPDF. При этом NextPDF не является готовым клоном-заменой FPDF: это современный движок PDF 2.0 со строгими типами, сабсеттингом шрифтов, подписью, PDF/A и доступностью (теговый PDF). Двумя настоящими сдвигами являются модель единиц измерения (NextPDF работает в пунктах PDF; FPDF по умолчанию использует миллиметры) и глаголы вывода (типизированное перечисление OutputDestination вместо символов 'I'/'D'/'F'/'S' в FPDF).

В ядре нет прослойки класса FPDF. Перепишите каждую точку вызова по сопоставлению глаголов. Если вам нужно наименьшее начальное изменение для кодовой базы TCPDF 6.x, см. адаптер совместимости с TCPDF, который поставляет почти исходно-совместимый путь готовой замены; для FPDF такого адаптера нет.

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

Оставьте setasign/fpdf (или ваш fpdf/fpdf) установленным на время переноса. Удалите его после финального переключения (см. безопасную последовательность переноса).

FPDF и NextPDF разделяют одну и ту же мысленную модель: документ, состоящий из страниц, курсор (текущая позиция x/y) и глаголы, которые рисуют в позиции курсора или продвигают её. SetXY, Cell, Ln и MultiCell читают и изменяют курсор в обеих библиотеках, поэтому большая часть процедурного кода FPDF переводится строка в строку.

Различия преднамеренны, а не случайны:

  • Единицы измерения. Конструктор FPDF (new FPDF($orientation, $unit, $size)) по умолчанию использует миллиметры. NextPDF работает в пунктах PDF (1 pt = 1/72 in, ISO 32000-2 §7). Общедокументного переключателя единиц нет — переведите мм в пункты один раз (pt = mm * 72 / 25.4).
  • Направление Y для вас остаётся прежним. Как и в FPDF, пользовательские координаты NextPDF помещают y = 0 в верх страницы и увеличиваются вниз, поэтому арифметика курсора переносится напрямую. NextPDF внутренне преобразует в нативное для PDF начало координат в нижнем левом углу.
  • Создание объекта явное. FPDF складывает ориентацию, единицу и размер в конструктор; NextPDF принимает неизменяемый объект-значение NextPDF\Core\Config (размер страницы, поля, каталог шрифтов) и явный addPage().
  • Всегда Unicode, всегда подмножество. Базовая сборка FPDF — Latin-1 и для Unicode требует варианта tFPDF/UTF-8. NextPDF — UTF-8 повсюду и всегда встраивает шрифты как программы-подмножества (ISO 32000-2 §9). Файлы AddFont/метрик шрифтов FPDF не имеют аналога; зарегистрируйте каталог шрифтов TrueType/OpenType и выберите семейство по имени.

Используемые ниже основные точки входа — Document::createStandalone(), Document::addPage(), Document::setFont(), Document::cell(), Document::multiCell(), Document::text(), Document::write(), Document::ln(), Document::image(), аксессоры курсора (setXY/setX/ setY/getX/getY), Document::output(?string, OutputDestination), Document::save(string $path): void, Document::getPdfData(): string и объект-значение NextPDF\Core\Config. Полный справочник по этим основным методам отрисовки, текста и вывода находится в основных модулях и указателе справочника, автогенерируемых из PHPDoc. Модуль Html — сопутствующее чтение по преобразованию HTML в PDF, а не справочник по глаголам этой страницы.

Имена публичных методов FPDF давно сложились и хорошо известны. Колонка NextPDF ниже сверена с сигнатурами исходного кода ядра (см. Доказательства / прослеживаемость).

FPDFNextPDFПримечания
new FPDF($orient, $unit, $size)Document::createStandalone($config)Аргументы конструктора orientation/unit/size становятся NextPDF\Core\Config (pageSize, margins, fontsDirectory). Нет $unit — работайте в пунктах. Страница по умолчанию у createStandalone() — A4 книжной ориентации.
$pdf->AddPage($orient, $size)$doc->addPage($size, $orientation)Прямое соответствие. $size — объект-значение PageSize; $orientation — перечисление Orientation (Portrait/Landscape).
$pdf->SetFont($family, $style, $size)$doc->setFont($family, $style, $size)Прямое соответствие. $style использует те же коды ''/'B'/'I'/'BI' (плюс подчёркивание 'U').
$pdf->Cell($w, $h, $txt, $border, $ln, $align, $fill)$doc->cell($w, $h, $txt, $border, $newLine, $align, $fill)Прямое соответствие. $align — перечисление Alignment (Left/Center/Right/Justify); $border принимает bool или строку 'LTRB'; $ln становится bool $newLine.
$pdf->MultiCell($w, $h, $txt, $border, $align, $fill)$doc->multiCell($w, $h, $txt, $border, $align)Перенос по словам по реальным метрикам шрифта. Аргумента $fill нет; сначала закрасьте rect(), если нужен фон.
$pdf->Write($h, $txt, $link)$doc->write($h, $txt, $link)Текст, текущий от курсора; $link прикрепляет аннотацию-ссылку URL.
$pdf->Text($x, $y, $txt)$doc->text($x, $y, $txt)Текст в абсолютной позиции. Прямое соответствие.
$pdf->Ln($h)$doc->ln($h)Перенос строки к левому полю; 0 = высота строки по умолчанию.
$pdf->Image($file, $x, $y, $w, $h)$doc->image($file, $x, $y, $w, $h)Прямое соответствие; $x/$y/$w/$h допускают null (null = текущий курсор / собственный размер).
$pdf->SetXY($x, $y) / SetX / SetY$doc->setXY($x, $y) / setX / setYПрямое соответствие. getX()/getY() читают курсор.
$pdf->SetMargins($l, $t, $r)$doc->setMargins(new Margin($t, $r, $bottom, $l))Один объект-значение Margin; порядок конструктора — (top, right, bottom, left), а не FPDF-овский (left, top, right). У FPDF SetMargins нет аргумента нижнего поля (его нижнее поле задаётся через SetAutoPageBreak($auto, $margin)), поэтому выберите $bottom сами — обычно равным верхнему полю или передайте поле авторазбивки страниц.
$pdf->SetAutoPageBreak($auto, $margin)$doc->setAutoPageBreak($auto, $margin)Прямое соответствие.
$pdf->SetDrawColor / SetFillColor / SetTextColor$doc->setDrawColor / setFillColor / setTextColorRGB (r, g, b) или одно значение для оттенков серого.
$pdf->Line / Rect / SetLineWidth$doc->line / rect / setLineWidthПрямое соответствие. rect() принимает строку стиля ('S'/'F'/'DF').
$pdf->SetTitle/SetAuthor/SetSubject/SetKeywords/SetCreator$doc->setTitle/setAuthor/setSubject/setKeywords/setCreatorПрямое соответствие. Попадает в словарь информации о документе ISO 32000-2 §14 / Extensible Metadata Platform (XMP).
$pdf->Output($dest, $name)$doc->output($name, OutputDestination::…)Символы назначения FPDF (I/D/F/S) соответствуют перечислению OutputDestination; обратите внимание на смену порядка аргументов (в NextPDF имя первым).
$pdf->Output('S')$doc->getPdfData()Возвращает байты PDF.
$pdf->Output('F', $path)$doc->save($path)Записывает по пути к файлу.
$pdf->GetStringWidth($s)(нет публичного метода)Ширина строки вычисляется внутренне во время переноса в cell()/multiCell(); публичного глагола измерения отдельной строки нет. Управляйте переносом через multiCell(), а не измеряйте вручную.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;
use NextPDF\Core\Document;
// FPDF:
// $pdf = new FPDF(); // mm, A4 portrait
// $pdf->AddPage();
// $pdf->SetFont('Arial', 'B', 16);
// $pdf->Cell(40, 10, 'Invoice');
// $pdf->Output('F', 'out.pdf');
// NextPDF — points, default page is A4 portrait:
$doc = Document::createStandalone();
$doc->setTitle('Invoice');
$doc->addPage();
$doc->setFont('Helvetica', 'B', 16.0);
$doc->cell(113.4, 28.3, 'Invoice', false, true, Alignment::Left); // ~40mm x ~10mm in points
$doc->save(__DIR__ . '/out.pdf');
echo "Wrote out.pdf\n";

Этот пример согласован с examples/04-text-and-fonts.php. В нём используются явный размер страницы, поля, зарегистрированный каталог шрифтов и управляемая курсором модель cell, которую уже использует кодовая база FPDF.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\Alignment;
use NextPDF\Contracts\OutputDestination;
use NextPDF\Core\Config;
use NextPDF\Core\Document;
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
// Equivalent of: new FPDF('P', 'mm', 'A4') + SetMargins(20, 16, 20)
// i.e. FPDF left=20mm, top=16mm, right=20mm. FPDF SetMargins has no bottom
// argument, so we pick bottom = top = 16mm. Convert each mm to points
// (pt = mm * 72 / 25.4): 16mm = 45.354pt, 20mm = 56.693pt.
// Margin constructor order is (top, right, bottom, left) — NOT FPDF's (L, T, R).
$config = new Config(
pageSize: new PageSize(595.276, 841.890, 'A4'),
margins: new Margin(45.354, 56.693, 45.354, 56.693), // top,right,bottom,left in points
fontsDirectory: __DIR__ . '/fonts',
);
$doc = Document::createStandalone($config);
$doc->setTitle('Quarterly Report');
$doc->setAuthor('Finance');
$doc->addPage();
// SetFont + Cell, the FPDF way — but in points and with a real Unicode font.
$doc->setFont('DejaVuSans', 'B', 18.0);
$doc->setTextColor(30, 58, 138);
$doc->cell(0, 24.0, 'Quarterly Report', false, true, Alignment::Left);
$doc->setFont('DejaVuSans', '', 11.0);
$doc->setTextColor(0, 0, 0);
$doc->multiCell(0, 16.0, "Body text wraps on real font metrics. Unicode is "
. "native, so accented and non-Latin characters need no tFPDF variant — "
. "register the family in the fonts directory and select it by name.");
// Equivalent of $pdf->Output('D', 'report.pdf'):
$doc->output('report.pdf', OutputDestination::Download);
  • Единицы измерения. Каждая числовая координата, ширина, высота и поле, которые вы копируете из FPDF, по умолчанию в миллиметрах. Умножьте на 72 / 25.4, чтобы получить пункты, один раз, во время переноса. Смешивание двух единиц молча мис-размеряет всё.
  • Порядок аргументов Output(). В FPDF это Output($dest, $name); в NextPDF — output($name, $dest). Назначение — перечисление OutputDestination, а не символ. Для вывода в файл / строку предпочитайте save() / getPdfData().
  • Порядок SetMargins. В FPDF это (left, top, right); объект-значение Margin NextPDF — (top, right, bottom, left). Переупорядочьте, а не переписывайте дословно.
  • Шрифты. Файлы AddFont() + .php-метрики FPDF не имеют эквивалента. Поместите файл TrueType/OpenType в каталог шрифтов и вызовите setFont() с именем семейства. Имена Base14 ядра (Helvetica, Times, Courier) разрешаются без файла; под PDF/A или теговым PDF они автоматически заменяются встраиваемым шрифтом.
  • GetStringWidth. Публичного метода измерения строки нет. Если ваш код FPDF измеряет строки, чтобы вручную выкладывать столбцы, переключите этот блок на multiCell() (который переносит по метрикам) или вызовы cell() фиксированной ширины.

NextPDF выдаёт содержимое за один потоковый проход (запись об архитектурном решении ADR-001); пиковая память зависит от размера документа, а не от удерживаемого дерева объектов. Бюджет для примера из этого руководства: wall_ms: 2000, peak_mb: 128. Для длинных документов выводите содержимое по вызовам addPage() — той же формы цикла, которую уже использует отчёт FPDF.

  • Метаданные. SetTitle()/SetAuthor() соответствуют типизированным сеттерам, записывающим в словарь информации о документе ISO 32000-2 §14 / XMP. Никогда не храните там секреты.
  • Пути к изображениям. image() отклоняет схемы stream-wrapper и встроенные байты NUL до чтения. Передавайте контролируемые приложением пути.
  • Никакого кода внутри документа. NextPDF не выполняет встроенные в документ сценарии; ничто в FPDF этого не меняет.
УтверждениеСпецификацияПункт
Format/orientation страницы соответствуют граничному боксу страницы.ISO 32000-2§7
Шрифты записываются как embedded/subset программы шрифтов.ISO 32000-2§9
Заголовок / метаданные попадают в словарь информации / XMP.ISO 32000-2§14
Линии, прямоугольники и изображения — это отрисовка content-stream.ISO 32000-2§8

NextPDF производит содержимое ISO 32000-2; он не утверждает визуальной идентичности с FPDF. Повторно проверяйте вывод при каждой смене рендерера.

Неприменимо. Ядро NextPDF покрывает описанный здесь путь перехода с FPDF.


Подробности перехода (обязательные разделы R6)

Заголовок раздела «Подробности перехода (обязательные разделы R6)»

Команды, использующие FPDF (или tFPDF) для серверной процедурной генерации PDF. Если ваш код — это последовательность вызовов AddPage / SetFont / Cell / MultiCell / Image / Output, управляемых SetXY и Ln, то сопоставление глаголов покрывает всю вашу поверхность.

В области охвата: глаголы отрисовки FPDF, модель курсора, шрифты, цвета, линии и прямоугольники, метаданные и вывод. Вне области охвата: инструментарий метрик-файлов AddFont FPDF и сторонние скрипт-расширения FPDF (штрихкоды, поворот, закладки) — сопоставьте их с соответствующими модулями NextPDF (Barcode, Transforms, Navigation), которые здесь не рассматриваются.

Поведенческая совместимость, а не готовая прослойка: ядро не предоставляет прослойку класса FPDF. Перепишите каждую точку вызова. Глаголы близко выстраиваются, потому что cell/text-API NextPDF разделяет линию FPDF/TCPDF, но модель единиц, порядок аргументов Output и типы Margin/перечислений различаются — поэтому дословная переписка ошибочна, а перевод верен.

Конструкция FPDFNextPDFПримечания
$unit ('mm' по умолчанию)(нет эквивалента)Работайте в пунктах PDF. Преобразуйте размеры через pt = mm * 72 / 25.4 один раз во время переноса.
$orientation ('P'/'L')перечисление Orientation в addPage() или поменять местами PageSize width/heightАльбомная = ширина > высоты.
$size ('A4', [w,h])Config->pageSize (объект-значение PageSize)Именованные форматы становятся явными размерами в пунктах; фабрики PageSize::A4()A0() и Letter/Legal существуют.
SetMargins($l, $t, $r)Config->margins (VO Margin)Порядок конструктора (top, right, bottom, left).
AddFont($family, $style, $file)каталог шрифтов + setFont() по имениОткажитесь от метрик-файла; поместите TTF/OTF в Config->fontsDirectory.
  • Каталоги шрифтов. Регистрация шрифтов по одному через AddFont в FPDF сводится к каталогу шрифтов плюс сопоставление семейства setFont(). Начните с Config->fontsDirectory (путь поиска по умолчанию); регистрируйте дополнительные каталоги через FontRegistry::addFontDirectory() или Document::addFontDirectory(), когда шрифты лежат в нескольких местах.
  • Всегда Unicode. Нет умолчания Latin-1 и нет отдельной сборки tFPDF; ввод в UTF-8 — норма.
  • Всегда подмножество. NextPDF всегда создаёт подмножества встроенных шрифтов (ISO 32000-2 §9); выборы встраивания шрифтов FPDF не имеют эквивалента и не нужны.
  • Заново зафиксируйте эталон глифов. Сопоставление и резерв шрифтов специфичны для движка; псевдониму шрифта FPDF может потребоваться точное имя семейства. Различия в подстановке ожидаемы, а не являются дефектами.
  • Преобразование единиц (мм → pt) — самая частая ошибка переноса; см. выше.
  • Смена порядка аргументов Output и переход назначения в перечисление.
  • Margin / Alignment / Orientation — типизированные объекты/перечисления, а не символы или позиционные тройки (l, t, r).
  • Нет публичного GetStringWidth — управляйте переносом через multiCell().
  • Независимая растеризация — перенос строк и разбивка на страницы на плотном содержимом могут различаться; заново зафиксируйте эталон визуальных различий.

Это документированные поведенческие различия, а не дефекты ни одного из движков.

Не поддерживается / нет прямого эквивалента

Заголовок раздела «Не поддерживается / нет прямого эквивалента»
  • Селектор $unit FPDF — не моделируется (всегда пункты).
  • Файлы AddFont() + .php/.z-метрики — заменены каталогом шрифтов.
  • GetStringWidth() — нет публичного глагола измерения строки.
  • Символы назначения 'I'/'D'/'F'/'S' в FPDF — заменены перечислением OutputDestination + save()/getPdfData().

Код, зависящий от них, не “мигрирует” дословно. Перевыразите его строками выше.

  1. Добавьте nextpdf/core рядом с FPDF; пока оставьте FPDF установленным.
  2. Выберите один документ с низким риском. Преобразуйте конструктор по карте единиц, затем перенесите каждый глагол по карте глаголов. Преобразуйте каждую координату в мм в пункты.
  3. Поместите шрифты документа в Config->fontsDirectory и выбирайте их по имени семейства; откажитесь от вызовов AddFont.
  4. Сгенерируйте оба PDF для одного и того же входа и визуально сравните их. Различия (подстановка шрифтов, перенос строк) ожидаемы для независимых движков — принимайте их для каждого документа.
  5. Замените любую ручную выкладку на основе GetStringWidth на multiCell() или вызовы cell() фиксированной ширины.
  6. Повторяйте для каждого документа, начиная с наименее рискованных; сохраняйте FPDF установленным до последнего переключения.
  7. Удалите FPDF из composer.json после финального переключения.
  • Сохраните снимок вывода FPDF для репрезентативных документов до изменения кода (эталонные входные данные; байты будут отличаться).
  • Для каждого перенесённого документа подтверждайте приёмку собственной проверкой (визуальное сравнение + извлечение текста). Поведение cell/font NextPDF задействуется в examples/04-text-and-fonts.php и наборах тестов Font и text-output ядра tests/. Приёмка перехода зависит от конкретного документа и остаётся вашей ответственностью.
  • Добавьте регрессионный тест для каждого перенесённого документа.

Каждое утверждение о поведении NextPDF на этой странице подкреплено сигнатурой исходного кода в репозитории, примером или записью об архитектурном решении (ADR), либо — для свойств формата PDF — пунктами ISO 32000-2 в поле фронтматтера citations: и таблице Соответствие. О поведении FPDF говорится только как о “независимом движке — ожидайте документированных различий”; эта страница не заявляет паритета, который не доказан артефактом в репозитории.

Утверждение о поведении NextPDFДоказательство в репозитории (путь)
AddPage соответствует addPage(?PageSize, Orientation): static.src/Core/Concerns/HasPages.php (addPage()).
SetFont($family, $style, $size) соответствует setFont(string, string, float): static; стили ''/'B'/'I'/'BI'/'U'.src/Core/Concerns/HasTypography.php (setFont()).
Cell соответствует cell($w, $h, $txt, $border, $newLine, $align, $fill): static.src/Core/Concerns/HasTextOutput.php (cell()).
MultiCell соответствует multiCell($w, $h, $txt, $border, $align): static (перенос по метрикам).src/Core/Concerns/HasTextOutput.php (multiCell(), wrapText()).
Write/Text/Ln соответствуют write()/text()/ln().src/Core/Concerns/HasTextOutput.php (write(), text(), ln()).
SetXY/SetX/SetY/GetX/GetY соответствуют напрямую; SetMargins принимает VO Margin.src/Core/Concerns/HasPages.php (setXY(), getX(), setMargins()); src/ValueObjects/Margin.php ((top, right, bottom, left)).
Image соответствует image($file, ?$x, ?$y, ?$w, ?$h): static; отклоняет пути со схемой/NUL.src/Core/Concerns/HasImages.php (image(), assertImageFilePath()).
Line/Rect/SetLineWidth/SetDrawColor/SetFillColor/SetTextColor соответствуют напрямую.src/Core/Concerns/HasDrawing.php (line(), rect(), setLineWidth()); src/Core/Concerns/HasColors.php (setDrawColor(), setFillColor(), setTextColor()).
createStandalone() — страница по умолчанию A4 книжной ориентации (595.276 × 841.890 pt).src/Core/Document.php (createStandalone()); src/ValueObjects/PageSize.php (A4()).
Назначение вывода — перечисление OutputDestination (Inline/Download/File/String); Output('S')getPdfData(), Output('F', $p)save($p).src/Contracts/OutputDestination.php; src/Core/Concerns/HasOutput.php (output()).
SetTitle/SetAuthor/… соответствуют типизированным сеттерам метаданных; попадают в словарь информации / XMP.src/Core/Concerns/HasMetadata.php (setTitle(), setAuthor()); ISO 32000-2 §14 (фронтматтер citations:).
Шрифты всегда встраиваются как программы-подмножества.src/Core/Concerns/HasTypography.php (buildFontData()); ISO 32000-2 §9 (фронтматтер citations:).
Содержимое выдаётся за один проход.docs/architecture/adr/ADR-001-stream-based-rendering-pipeline.md.

Оба пакета остаются установленными до финального переключения, поэтому откат для отдельной точки вызова означает возврат этой точки вызова к реализации FPDF. После финального переключения откат означает восстановление FPDF и предыдущего кода из системы контроля версий. Миграция данных не требуется.

См. Производительность. Однопроходная модель устраняет любые затраты на удержание буфера. Новые затраты на каждый документ — это раннее разрешение шрифтов (шаг 3), которое можно кешировать через каталог шрифтов.

  • Переписывание координат в миллиметрах как пунктов без преобразования * 72 / 25.4.
  • Оставление Output() в FPDF-овском порядке ($dest, $name) или передача символа вместо перечисления OutputDestination.
  • Переписывание SetMargins($l, $t, $r) напрямую в Margin (чей порядок — top, right, bottom, left).
  • Ожидание, что метрик-файлы AddFont перенесутся; вместо этого поместите TTF/OTF в каталог шрифтов.
  • Поиск эквивалента GetStringWidth; используйте multiCell() для переноса.
  • Ожидание byte/pixel-identical вывода (независимые движки — это руководство никогда не заявляет о готовой замене или 100%-й совместимости).