Skip to content

Barcodes and QR Codes

Dragon edited this page Jun 4, 2026 · 2 revisions

Barcodes and QR Codes

PhpPdf includes a built-in barcode engine that renders 1D linear codes and 2D matrix codes directly into a PDF page. All formats share a single Page::barcode() method and are configured through immutable value objects.

Basic examples

use DragonOfMercy\PhpPdf\Color;
use DragonOfMercy\PhpPdf\Barcode\{Ean13, Ean8, Code128, QrCode, ErrorCorrection, AztecCode, AztecEc};

// EAN-13 with 12 digits (check digit auto-computed) and human-readable text below.
$page->barcode(Ean13::of('978013110362'), x: 20, y: 20, w: 50, h: 18);

// Code 128, no human text, custom red color.
$page->barcode(
    Code128::of('SHIP-2026-001')->withoutText()->withColor(Color::rgb(192, 0, 0)),
    x: 20, y: 50, w: 70, h: 12,
);

// QR Code with high error-correction (30%) and a branded color.
$page->barcode(
    QrCode::of('https://example.com')
        ->withErrorCorrection(ErrorCorrection::H)
        ->withColor(Color::hex('#003366')),
    x: 130, y: 20, w: 40,
);

// Aztec Code with default MEDIUM EC (auto-fits Compact 1-4 or Full Range 1-32).
$page->barcode(AztecCode::of('https://example.com'), x: 20, y: 80, w: 30);

// Aztec with HIGH EC and a UTF-8 payload (ECI prefix emitted automatically).
$page->barcode(
    AztecCode::of('Cafe Naivete Oeuvre')
        ->withErrorCorrection(AztecEc::HIGH)
        ->withColor(Color::hex('#003366')),
    x: 60, y: 80, w: 30,
);

Standards supported

Format Class Notes
EAN-13 (ISO/IEC 15420) Ean13 12 or 13 digits, auto checksum
EAN-8 Ean8 7 or 8 digits, auto checksum
Code 128 (ISO/IEC 15417) Code128 ASCII 0-127, auto-switches A/B/C sets
UPC-A Upca 11 or 12 digits, auto checksum
Code 39 Code39 Uppercase letters, digits, and a small symbol set
Code 93 Code93 Full ASCII via two-character encoding
ITF (Interleaved 2 of 5) Itf Even-length digit strings; optional GS1 bearer bar via withBearerBar(?float $modules = null) (default 2 modules thick)
QR Code (ISO/IEC 18004) QrCode V1-V40, error correction L/M/Q/H, numeric/alphanumeric/byte modes
Aztec Code (ISO/IEC 24778) AztecCode Compact (1-4 layers) and Full Range (1-32 layers), EC presets LOW/MEDIUM/HIGH/MAX
DataMatrix (ISO/IEC 16022) DataMatrix ECC200 only, 24 square sizes 10x10 to 144x144, no EC knob
PDF417 (ISO/IEC 15438) Pdf417 Standard stacked variant, EC levels 0-8, optional column hint

Page::barcode() API

Page::barcode(
    Barcode    $code,
    ?float     $x  = null,
    ?float     $y  = null,
    ?float     $w  = null,
    ?float     $h  = null,
    NextPosition $ln = NextPosition::NONE,
): void
  • $x / $y - top-left corner in the document unit (mm by default). Defaults to the current cursor position when null (same cursor as cell()).
  • $w / $h - width and height in the document unit.
    • 1D codes (EAN-13, EAN-8, Code 128, UPC-A, Code 39, Code 93, ITF): $h is required. $w may be omitted when a module size is set (see SizedBarcode below).
    • Square 2D codes (QR, Aztec, DataMatrix): only $w is needed; $h defaults to $w. Passing $h != $w raises a PdfException.
    • PDF417: $h is optional and unconstrained. When null it is derived from the symbol's row count.
  • $ln - cursor advance after the barcode (see Cursor flow below).

Coordinates use the document unit with a top-down Y axis, consistent with the rest of the API. The quiet zone is included in the $w / $h you provide. Default color is black regardless of the page's current fill color.

Value object API

Every barcode is created via a static named constructor and configured through immutable withers:

Method Applies to Description
::of(string $data) all Validates the payload and returns a new instance
->withColor(Color $color) all Sets the module color (default: black)
->withoutText() 1D codes Suppresses the human-readable text line
->withErrorCorrection(ErrorCorrection $ec) QrCode L / M / Q / H
->withErrorCorrection(AztecEc $ec) AztecCode LOW / MEDIUM / HIGH / MAX
->withErrorCorrection(int $level) Pdf417 0-8; auto-selected when omitted
->withColumns(int $cols) Pdf417 Optional column-count hint

ErrorCorrection cases: L, M, Q, H. AztecEc cases: LOW (~10%), MEDIUM (~23%), HIGH (~36%), MAX (~50%).

1D auto-width via module size (SizedBarcode)

All seven 1D codes implement the SizedBarcode interface. When you set a module width, $w may be omitted from barcode() and is computed automatically:

use DragonOfMercy\PhpPdf\Barcode\Code128;

// Render Code 128 with 0.33 mm narrow modules; width is auto-derived.
$page->barcode(Code128::of('ABC')->withModuleSize(0.33), x: 20, y: 20, h: 18);

// Query the width without rendering.
$w = Code128::of('ABC')->withModuleSize(0.33)->widthForModule(0.33);
Method Description
->withModuleSize(float $moduleSize) Sets the narrow-module width in the document unit; returns a new instance
->widthForModule(float $moduleSize) Returns the total width (quiet zones included) for the given module size, without rendering

1D barcode orientation (OrientableBarcode)

All 1D codes implement OrientableBarcode. Use ->vertical() to rotate the barcode 90 degrees counter-clockwise (bars run bottom-to-top). The logical $w / $h parameters keep their meaning - in vertical mode the visual footprint is $h wide by $w tall, anchored at ($x, $y):

use DragonOfMercy\PhpPdf\Barcode\Code128;

$page->barcode(Code128::of('ABC')->vertical(), x: 20, y: 20, w: 70, h: 18);
Method Description
->vertical() Returns a copy drawn vertically (quarter-turn CCW)
->horizontal() Returns a copy drawn horizontally (the default)

2D codes (QR, Aztec, DataMatrix, PDF417) do not implement OrientableBarcode and cannot be rotated via this interface.

Cursor flow

barcode() defaults to NextPosition::NONE, which leaves the cursor untouched - typical for absolute placement. Pass $ln to advance after the barcode:

Value Behavior
NextPosition::NONE Cursor unchanged (default)
NextPosition::RIGHT Cursor moves to the right of the barcode's visual box
NextPosition::NEWLINE Cursor moves to a new line below the barcode
NextPosition::BELOW Cursor moves below the barcode, same X

A vertical 1D code advances by its rotated footprint. A square 2D code with a null $h advances by $w.

Recommended sizes and quiet zones

  • EAN-13: >= 25 mm wide for reliable retail scanning.
  • QR Code: module >= 0.5 mm (a V3 QR is about 15 mm minimum).
  • Aztec: module >= 0.5 mm (Compact 1-layer ~ 10 mm, Full Range 32-layer ~ 80 mm minimum).

The quiet zone mandated by each standard is already included in the $w / $h you supply. The barcode renderer wraps its output in a graphics save / restore (q ... Q), so it does not alter the page's current font or fill color.

See also

Clone this wiki locally