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

Создание одномерных и двумерных штрихкодов в PDF

В этом рецепте показано, как отрисовывать одномерные (1D) и двумерные (2D) штрихкоды прямо на странице Portable Document Format (PDF). Трейт Core HasBarcodes предоставляет методы write1DBarcode() и write2DBarcode(). Оба метода отрисовывают символ собственными операторами контуров PDF на текущей странице, поэтому получается простое детерминированное векторное содержимое. Рецепт основан на примере examples/10-barcodes.php.

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

Дополнительные расширения не требуются. Кодировщики штрихкодов написаны на чистом PHP, а NextPDF отрисовывает символы стандартным PDF-оператором прямоугольника (ISO 32000-2 §8.5).

Штрихкод отрисовывается, а не встраивается как изображение. Полезная нагрузка — это кодируемые данные, например номер товара или веб-адрес.

write1DBarcode() преобразует полезную нагрузку в шаблон bar/space для выбранного BarcodeType, а затем выводит последовательность заполненных прямоугольников. write2DBarcode() строит матрицу модулей для выбранного Barcode2DType и выводит по одному заполненному прямоугольнику для каждого тёмного модуля. Data Matrix и QR Code используют коррекцию ошибок Рида-Соломона, поэтому сканер может восстановить данные, даже если часть символа повреждена.

Каждый модуль — это детерминированный контур re … f без источника энтропии, поэтому содержимое самого штрихкода полностью воспроизводимо. Профиль воспроизводимости — structural, поскольку окружающий документ по-прежнему содержит элементы, которые меняются при каждом сохранении: /ID в трейлере, а также временные метки /CreationDate и /ModDate. Тестовая обвязка нормализует структуру через qpdf, удаляет эти элементы и сравнивает результат.

NextPDF\Core\Concerns\HasBarcodes (подмешивается в Document):

  • write1DBarcode(string $code, BarcodeType $type, ?float $x = null, ?float $y = null, float $w = 0, float $h = 30, float $barWidth = 0.4, bool $skipZeroWidthBars = true): static
  • write2DBarcode(string $code, Barcode2DType $type, ?float $x = null, ?float $y = null, float $w = 0, float $h = 0, float $moduleSize = 1.0, string $ecLevel = 'L', ?int $mask = null, ?int $version = null, bool $gs1 = false, bool $dmre = false, bool $rectangular = false): static

Символика — это стандарт штрихкода, который определяет, как данные превращаются в штрихи или модули. BarcodeType перечисляет одномерные символики (C128, EAN13, UPCA, I25, CODABAR, ISBN, GS1_128, …), а Barcode2DType — двумерные (QRCode, DataMatrix, PDF417, HanXin, MicroQR, …).

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Barcode\Barcode2DType;
use NextPDF\Barcode\BarcodeType;
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Barcode Quick Start');
$doc->addPage();
$doc->write1DBarcode('NEXTPDF-2026', BarcodeType::C128, x: 15, y: 30, w: 80, h: 20);
$doc->write2DBarcode('https://nextpdf.dev', Barcode2DType::QRCode, x: 15, y: 60, w: 40, h: 40);
$doc->save(__DIR__ . '/barcodes.pdf');
echo "Wrote barcodes.pdf\n";

Полный пример ниже готов к запуску в тестовой обвязке и повторяет examples/10-barcodes.php. Он записывает PDF по пути, который тестовая обвязка передаёт через NEXTPDF_COOKBOOK_OUTPUT, а при ручном запуске использует локальный файл. Так обвязка воспроизводимости может запустить его дважды и проверить структурную идентичность. Структура нормализуется через qpdf; при этом удаляются изменяющиеся при каждом сохранении элементы /ID и временные метки.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Barcode\Barcode2DType;
use NextPDF\Barcode\BarcodeType;
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Barcode Examples');
$doc->addPage();
$doc->setFont('helvetica', 'B', 18);
$doc->cell(0, 12, 'Barcode Examples', newLine: true);
$doc->ln(5);
// --- 1D barcodes ---
$doc->setFont('helvetica', 'B', 14);
$doc->cell(0, 10, '1D Barcodes', newLine: true);
$doc->ln(3);
$doc->setFont('helvetica', '', 10);
$doc->cell(0, 6, 'Code 128:', newLine: true);
$doc->write1DBarcode('NEXTPDF-2026', BarcodeType::C128, x: 15, y: null, w: 80, h: 20);
$doc->ln(28);
$doc->cell(0, 6, 'EAN-13:', newLine: true);
$doc->write1DBarcode('4006381333931', BarcodeType::EAN13, x: 15, y: null, w: 60, h: 20);
$doc->ln(28);
// --- 2D barcodes ---
$doc->setFont('helvetica', 'B', 14);
$doc->cell(0, 10, '2D Barcodes', newLine: true);
$doc->ln(3);
$doc->setFont('helvetica', '', 10);
$doc->cell(0, 6, 'QR Code (URL):', newLine: true);
$doc->write2DBarcode('https://nextpdf.dev', Barcode2DType::QRCode, x: 15, y: null, w: 40, h: 40);
$doc->ln(48);
$doc->cell(0, 6, 'DataMatrix:', newLine: true);
$doc->write2DBarcode('NextPDF-DM-2026', Barcode2DType::DataMatrix, x: 15, y: null, w: 30, h: 30);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
$doc->save($out !== false ? $out : __DIR__ . '/barcodes.pdf');
echo "Wrote barcodes PDF (Code 128, EAN-13, QR Code, DataMatrix)\n";

Ожидаемый вывод:

Wrote barcodes PDF (Code 128, EAN-13, QR Code, DataMatrix)
  • Допустимость полезной нагрузки зависит от символики. EAN13 ожидает 12 или 13 цифр. Некорректная полезная нагрузка вызывает исключение до того, как NextPDF запишет какое-либо содержимое. UPCA, ISBN и ISSN имеют собственные правила длины и контрольной цифры.
  • x/y необязательны. Если их опустить, штрихкод размещается в текущей позиции курсора. Передавайте явные координаты, чтобы макет был предсказуемым.
  • w = 0 включает автоматический подбор размера. Нулевая ширина позволяет кодировщику выбрать естественную ширину модуля. Передайте положительную ширину, чтобы вписать штрихкод в фиксированную область.
  • Уровень коррекции ошибок для 2D. write2DBarcode() по умолчанию использует ecLevel: 'L' — самый низкий уровень. Повысьте его ('M', 'Q', 'H') для QR Code, который должен выдерживать повреждения при печати. Более высокие уровни увеличивают матрицу.
  • Идентификаторы применения GS1. Передайте gs1: true в write2DBarcode() или используйте BarcodeType::GS1_128 для данных в структуре GS1 с префиксом FNC1.
  • Страница создаётся неявно. Если вызвать метод штрихкода до addPage(), NextPDF сначала добавит страницу. Это удобно, но вызывайте addPage() явно, когда важна геометрия страницы.

Кодирование имеет сложность O(длина полезной нагрузки) для 1D и O(площадь матрицы) для 2D; оба варианта выполняются за микросекунды. Каждый модуль — это один оператор контура re … f, поэтому плотный QR Code добавляет несколько килобайт к потоку содержимого. Этапа растеризации нет, поэтому потребление памяти остаётся неизменным независимо от размера символа. Рецепт уверенно укладывается в бюджет 1500 ms / 64 MB.

Штрихкод содержит любую переданную полезную нагрузку, поэтому на принимающей стороне относитесь к его значению как к любым другим недоверенным входным данным. Библиотека не подписывает и не аутентифицирует полезную нагрузку. Двумерный символ — это не шифрование: его может прочитать любой, у кого есть сканер.

УтверждениеСпецификацияПунктreference_id (идентификатор ссылки)
Модули штрихкода отрисовываются оператором построения прямоугольного контура.ISO 32000-2§8.5
Символы Code 128 используют определённую структуру элементов bar/space.ISO/IEC 15417§4.3.1
Символы Data Matrix применяют коррекцию ошибок Рида-Соломона.ISO/IEC 16022§7.6.1
Данные QR Code разбиваются на блоки коррекции ошибок.ISO/IEC 18004§7.5.2

NextPDF реализует перечисленные кодировки символик, но не заявляет о формальной сертификации по стандартам штрихкодов. Документы корпуса по символикам штрихкодов ограничены лицензией до уровня Tier C. Ссылки используют только указатели clause-id и reference_id, при этом текст стандарта не воспроизводится.