Skip to content

Barcode: 1D and 2D symbology encoders

The Barcode module provides the symbology implementation layer. It encodes linear symbologies (Code 128, EAN, UPC, Interleaved 2 of 5, Codabar, postal codes) and matrix symbologies (QR Code, Data Matrix, PDF417). It computes error correction and registers each encoder behind the barcode contracts, so the document writer can paint the result. The contract definitions live on a separate page. See the note below.

One canonical page per concern. The interfaces an encoder satisfies (Barcode1DEncoderInterface, Barcode2DEncoderInterface, BarcodeEncoderInterface, Gs1DataParserInterface) are documented on Contracts / Barcode. This page documents the concrete encoders that implement those contracts. The pages are complementary, not duplicates. Read the contracts page for the service provider interface (SPI). Read this page for the symbologies.

Terminal window
composer require nextpdf/core:^3

A barcode encoder turns a payload string into a two-dimensional (2D) module matrix or a one-dimensional (1D) bar sequence that the writer paints as Portable Document Format (PDF) graphics. This module provides the concrete encoders.

Barcode1D is the linear engine. BarcodeType enumerates the supported linear symbologies: Code 39 (with and without checksum), Code 93, the Code 128 family, EAN-8/EAN-13, UPC-A/UPC-E, Interleaved and Standard 2 of 5, Codabar, Code 11, POSTNET, PLANET, Intelligent Mail (IMB), and MSI. generate() returns a BarcodeData value object describing the bar pattern.

The 2D encoders, QrEncoder, DataMatrixEncoder, and Pdf417Encoder, implement BarcodeEncoderInterface and return a Barcode2DData matrix. Barcode2DType enumerates the matrix symbologies the engine recognizes, including QR Code, Data Matrix, and PDF417. Additional symbologies such as Micro QR, rMQR, GS1 DataBar, and Han Xin are enumerated for registry routing. The encoder set that backs each symbology is edition-dependent. Matrix error correction is computed over a Galois field. GaloisField and GaloisFieldPrime provide the Reed-Solomon arithmetic shared by the QR, Data Matrix, and PDF417 encoders.

BarcodeEncoderRegistry is the lookup. It implements PHP Standards Recommendation 11 (PSR-11) ContainerInterface, provides default registration through createDefault(), and resolves a symbology to its encoder with resolve(). Application code rarely accesses an encoder directly. The high-level Document::write1DBarcode() / write2DBarcode() facade names a symbology and the registry supplies the encoder. The 1D engine is @since 1.0.0. The 2D encoders are @since 1.3.0. The registry is @since 3.0.0.

ClassKey membersRole
Barcode1Dgenerate(string $code, BarcodeType $type): BarcodeDataLinear-symbology encoder (@since 1.0.0)
QrEncoderencode(string $data, array $options = []): Barcode2DDataQR Code encoder (@since 1.3.0)
DataMatrixEncoderencode(string $data, array $options = []): Barcode2DDataData Matrix encoder (@since 1.3.0)
Pdf417Encoderencode(string $data, array $options = []): Barcode2DDataPDF417 encoder (@since 1.3.0)
BarcodeEncoderRegistrycreateDefault(), register(), resolve(), has(), get(), registered()PSR-11 encoder registry (@since 3.0.0)
BarcodeType / Barcode2DTypeenum casesSupported symbology enumerations
GaloisField / GaloisFieldPrimefinite-field arithmeticReed-Solomon error correction

Run composer docs:generate-api-php -- --module=Barcode to generate the full PHPDoc table.

Source: examples/10-barcodes.php. The facade resolves the encoder for the requested symbology through the registry.

<?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->addPage();
$doc->write1DBarcode('4006381333931', BarcodeType::EAN13, x: 15, y: null, w: 60, h: 20);
$doc->write2DBarcode('https://nextpdf.dev', Barcode2DType::QRCode, x: 15, y: 40, w: 40, h: 40);
$doc->save(__DIR__ . '/output/10-barcodes.pdf');

Resolve a 2D encoder directly through the registry, and bound the payload before encoding.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Barcode\Barcode2DType;
use NextPDF\Barcode\BarcodeEncoderRegistry;
use NextPDF\Exception\BarcodeException;
use Psr\Log\LoggerInterface;
final readonly class TrackingCodeService
{
private const int MAX_PAYLOAD = 512;
public function __construct(
private BarcodeEncoderRegistry $registry,
private LoggerInterface $logger,
) {}
/** @return \NextPDF\Barcode\Barcode2DData */
public function encode(string $trackingId): \NextPDF\Barcode\Barcode2DData
{
if (strlen($trackingId) > self::MAX_PAYLOAD) {
throw new \LengthException('Tracking payload exceeds the encode bound.');
}
try {
$encoder = $this->registry->resolve(Barcode2DType::QRCode->value);
return $encoder->encode($trackingId, ['errorCorrection' => 'high']);
} catch (BarcodeException $e) {
$this->logger->error('Barcode encode failed', ['error' => $e->getMessage()]);
throw $e;
}
}
}
  • A linear payload that violates a symbology’s character set or check-digit rule raises BarcodeException. EAN/UPC compute and append the check digit. Do not pre-append it.
  • The 2D $options array is symbology-specific, such as an error-correction level for QR. Most encoders ignore unknown keys. Verify each key against the encoder’s own documentation.
  • Barcode2DType enumerates more symbologies than the core edition ships encoders for. BarcodeEncoderRegistry::resolve() raises for an unregistered symbology instead of returning a placeholder.
  • Registered encoders are shared instances. Keep them stateless beyond constructor configuration. Per-call state corrupts concurrent renders.
  • An overlong payload produces a denser, larger matrix. Bound payload length before encoding to avoid denial of service through symbol size.

Encoding cost scales with payload length and matrix size, not with the registry lookup, which is O(1). A short Code 128 payload encodes in microseconds. A dense QR Code with high error correction is the heaviest case. The multi-symbol example page stays inside the 1500 ms wall / 64 MB peak budget. The reproducibility profile is bitwise. The same payload and options always produce the same module matrix and the same painted bytes.

Barcode payloads often come from untrusted sources: a scanned uniform resource locator (URL), a serial number, or a tracking code. The encoders encode bytes. They do not interpret them. A QR Code that encodes a hostile URL is still a valid QR Code, so the consumer is responsible for payload trust. Bound payload length before encoding to keep matrix size, work, and output size within a budget. Treat any data decoded from a barcode elsewhere as untrusted input when it re-enters the application. See the engine threat model in /modules/core/security/.

ClaimStandardReference
QR Code symbols follow the QR Code matrix symbology specification.ISO/IEC 18004QR Code symbology
Data Matrix symbols follow the Data Matrix symbology specification.ISO/IEC 16022Data Matrix symbology
PDF417 symbols follow the PDF417 symbology specification.ISO/IEC 15438PDF417 symbology
Code 128 symbols follow the Code 128 linear symbology specification.ISO/IEC 15417Code 128 symbology
EAN/UPC symbols follow the EAN/UPC symbology specification.ISO/IEC 15420EAN/UPC symbology

These symbology standards are not present in the verifiable citation corpus, so no reference_id is recorded. This page paraphrases the requirement and cites the source by number and clause. Consult the published standards for authoritative encoding rules. The encoders are exercised by tests/Unit/Barcode/. Correctness against the symbology specifications is the test suite’s responsibility, not a statement of end-to-end PDF conformance.