跳到內容

在 PDF 中產生 1D 與 2D 條碼

這篇 recipe(範例)會將 1D 與 2D 條碼直接繪製到 PDF 頁面上。核心的 HasBarcodes trait 提供 write1DBarcode()write2DBarcode()。兩者都會使用原生 PDF 路徑運算子,在目前頁面上繪製符號,因此輸出是純粹且具有確定性的向量內容。這篇 recipe 取材自 examples/10-barcodes.php

Terminal window
composer require nextpdf/core:^3

你不需要額外擴充功能。條碼編碼器是純 PHP,符號則以標準的 PDF 矩形運算子繪製(ISO 32000-2 §8.5)。

條碼是直接繪製出來,而不是以影像形式嵌入。payload 是你要編碼的資料,例如產品編號或網址。

write1DBarcode() 會將 payload 編碼成所選 BarcodeType 的 bar/space 樣式,再輸出一連串填滿的矩形。write2DBarcode() 會為所選 Barcode2DType 建構模組矩陣,並為每個暗模組輸出一個填滿的矩形。Data Matrix 與 QR Code 採用 Reed-Solomon 錯誤更正,因此即使符號的一部分受損,掃描器仍能還原資料。

每個模組都是一條確定性的 re … f 路徑,不含任何熵來源,因此條碼內容本身可完全重現。可重現性等級是 structural,因為周邊文件仍包含每次儲存時才會變動的原子值:trailer 的 /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

symbology(條碼編碼規格)指的是一類條碼標準,定義資料如何轉換成條或模組。BarcodeType 列出 1D symbology(C128EAN13UPCAI25CODABARISBNGS1_128 等),Barcode2DType 則列出 2D symbology(QRCodeDataMatrixPDF417HanXinMicroQR 等)。

<?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)
  • payload 的有效性會依 symbology 而異。 EAN13 需要 12 或 13 位數字。無效的 payload 會先擲出例外,不會寫入任何內容。UPCAISBNISSN 各有自己的長度與檢查碼規則。
  • x/y 是選用的。 省略它們時,條碼會放在目前游標位置。傳入明確的座標,可以得到可預測的版面配置。
  • w = 0 會自動調整尺寸。 寬度設為零時,編碼器會選擇自然的模組寬度。傳入正的寬度,即可放入固定的方框內。
  • 2D 錯誤更正等級。 write2DBarcode() 預設為 ecLevel: 'L',也就是最低等級。對於必須承受列印損傷的 QR Code,可以提高等級('M''Q''H')。等級越高,矩陣也會越大。
  • GS1 應用識別碼。gs1: true 傳入 write2DBarcode(),或改用 BarcodeType::GS1_128,即可處理含有 FNC1 前綴的 GS1 結構化資料。
  • 會隱含建立一個頁面。 當你在 addPage() 之前呼叫條碼方法時,NextPDF 會先補上一個頁面。這雖然方便,但在頁面幾何很重要時,請明確呼叫 addPage()

編碼複雜度在 1D 為 O(payload 長度)、2D 為 O(矩陣面積),兩者都在微秒等級。每個模組都是一個 re … f 路徑運算子,因此一個密集的 QR Code 會使內容串流增加幾 KB。過程不含點陣化步驟,因此無論符號多大,記憶體用量都維持平穩。這篇 recipe 仍能穩定落在 1500 ms / 64 MB 的預算之內。

條碼會承載你傳入的任何 payload,因此在消費端應將條碼值視為和其他任何不可信輸入一樣處理。這個函式庫不會替 payload 簽章,也不會驗證其真實性。2D 符號並不是加密:任何有掃描器的人都能讀取它。

陳述規格條款參考 ID
條碼模組使用矩形路徑建構運算子繪製。ISO 32000-2§8.5
Code 128 符號字元使用定義明確的 bar/space 元素結構。ISO/IEC 15417§4.3.1
Data Matrix 符號採用 Reed-Solomon 錯誤更正。ISO/IEC 16022§7.6.1
QR Code 資料會切分成多個錯誤更正區塊。ISO/IEC 18004§7.5.2

NextPDF 實作所引用的 symbology 編碼,但未聲稱已通過條碼標準的正式認證。條碼 symbology 語料庫文件受 Tier C 授權限制。引用僅以 clause-id 與 reference_id 指標標示,沒有重製任何標準原文。