Skip to content

Generate 1D and 2D barcodes in a PDF

This recipe draws one-dimensional (1D) and two-dimensional (2D) barcodes directly on a Portable Document Format (PDF) page. The Core HasBarcodes trait gives you write1DBarcode() and write2DBarcode(). Both methods draw the symbol as native PDF path operators on the current page, so the output is plain, deterministic vector content. The recipe follows examples/10-barcodes.php.

Terminal window
composer require nextpdf/core:^3

You do not need an extra extension. The barcode encoders are pure PHP, and NextPDF draws the symbols with the standard PDF rectangle operator (ISO 32000-2 §8.5).

A barcode is drawn, not embedded as an image. The payload is the data you encode, such as a product number or a web address.

write1DBarcode() encodes the payload into a bar/space pattern for the chosen BarcodeType, then emits a sequence of filled rectangles. write2DBarcode() builds a module matrix for the chosen Barcode2DType and emits one filled rectangle for each dark module. Data Matrix and QR Code use Reed-Solomon error correction, so a scanner can recover the data even when part of the symbol is damaged.

Every module is a deterministic re … f path with no entropy source, so the barcode content itself is fully reproducible. The reproducibility profile is structural because the surrounding document still carries per-save atoms: the trailer /ID, plus the /CreationDate and /ModDate timestamps. The harness compares the qpdf-normalised structure with those atoms stripped.

NextPDF\Core\Concerns\HasBarcodes (mixed into 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

A symbology is a barcode standard that defines how data becomes bars or modules. BarcodeType lists the 1D symbologies (C128, EAN13, UPCA, I25, CODABAR, ISBN, GS1_128, …), and Barcode2DType lists the 2D symbologies (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";

The complete, harness-runnable example below mirrors examples/10-barcodes.php. It writes the PDF to the path the harness supplies through NEXTPDF_COOKBOOK_OUTPUT, and falls back to a local file when you run it manually. The reproducibility harness can then run it twice and assert structural identity. The structure is qpdf-normalised, with the per-save /ID and timestamp atoms stripped.

<?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";

Expected output:

Wrote barcodes PDF (Code 128, EAN-13, QR Code, DataMatrix)
  • Payload validity is symbology-specific. EAN13 expects 12 or 13 digits. An invalid payload throws before NextPDF writes any content. UPCA, ISBN, and ISSN have their own length and check-digit rules.
  • x/y are optional. When you omit them, the barcode is placed at the current cursor position. Pass explicit coordinates for predictable layout.
  • w = 0 auto-sizes. A zero width lets the encoder pick a natural module width. Pass a positive width to fit a fixed box.
  • 2D error-correction level. write2DBarcode() defaults to ecLevel: 'L', the lowest level. Raise it ('M', 'Q', 'H') for QR Codes that must survive print damage. Higher levels enlarge the matrix.
  • GS1 application identifiers. Pass gs1: true to write2DBarcode(), or use BarcodeType::GS1_128, for GS1-structured data with the FNC1 prefix.
  • A page is created implicitly. When you call a barcode method before addPage(), NextPDF adds a page first. That is convenient, but call addPage() explicitly when page geometry matters.

Encoding is O(payload length) for 1D and O(matrix area) for 2D, and both run at microsecond scale. Each module is one re … f path operator, so a dense QR Code adds a few kilobytes of content stream. There is no rasterisation step, so memory stays flat regardless of symbol size. The recipe stays well inside the 1500 ms / 64 MB budget.

A barcode carries whatever payload you pass, so treat the barcode value like any other untrusted input on the consuming side. The library does not sign or authenticate the payload. A 2D symbol is not encryption: anyone with a scanner can read it.

StatementSpecClausereference_id
Barcode modules are drawn with the rectangle path-construction operator.ISO 32000-2§8.5
Code 128 symbol characters use the defined bar/space element structure.ISO/IEC 15417§4.3.1
Data Matrix symbols employ Reed-Solomon error correction.ISO/IEC 16022§7.6.1
QR Code data is split into error-correction blocks.ISO/IEC 18004§7.5.2

NextPDF implements the cited symbology encodings, but does not assert formal certification against the barcode standards. The barcode-symbology corpus documents are licence-capped at Tier C. Citations use clause-id and reference_id pointers only, and no standard text is reproduced.