# chillerlan/php-qrcode
chillerlan/php-qrcode is a comprehensive QR Code generator and reader library for PHP 8.2+. Based on Kazuhiko Arase's implementation and featuring a QR Code reader ported from the ZXing library, it provides a flexible, user-friendly API for creating and decoding QR codes. The library supports Model 2 QR Codes (Version 1 to 40) with all ECC levels (L/M/Q/H) and mixed encoding modes including numeric, alphanumeric, byte, Kanji, and Hanzi.
The library excels in its extensible output system, supporting 15+ output formats from raster images (PNG, JPEG, GIF, WebP, AVIF) to vector graphics (SVG, EPS), markup formats (HTML, XML), and document types (PDF). It offers extensive customization options including circular modules, custom colors, logo spaces, transparency, path connection, and per-module styling. The QR Code reader supports both GD and ImageMagick with preprocessing options for grayscale conversion, contrast enhancement, and color inversion.
## Generate Simple QR Code
Generate a QR Code with automatic settings using the default SVG output format.
```php
render('https://github.com/chillerlan/php-qrcode');
// Output to browser
header('Content-Type: image/svg+xml');
echo $svg;
// Or save to file
file_put_contents('qrcode.svg', $svg);
```
## Generate PNG Image QR Code
Create a raster PNG image with custom size, colors, and error correction level.
```php
version = 5; // QR version 1-40
$options->eccLevel = EccLevel::H; // Error correction: L, M, Q, H
$options->outputInterface = QRGdImagePNG::class; // PNG output
$options->scale = 10; // Pixels per module
$options->outputBase64 = true; // Data URI output
$options->bgColor = [255, 255, 255]; // White background RGB
$options->imageTransparent = false; // Disable transparency
try {
$qrcode = new QRCode($options);
$dataUri = $qrcode->render('https://www.example.com/product/12345');
// Use in HTML
tag
echo '
';
// Or output directly as PNG
$options->outputBase64 = false;
$pngData = $qrcode->render('https://www.example.com/product/12345');
header('Content-Type: image/png');
echo $pngData;
} catch (Throwable $e) {
error_log('QR Code generation failed: ' . $e->getMessage());
exit('Error generating QR code');
}
```
## Generate SVG with Custom Styling
Create an SVG QR Code with circular modules, gradients, and custom styling using SVG defs.
```php
version = 7;
$options->outputInterface = QRMarkupSVG::class;
$options->outputBase64 = false;
$options->drawLightModules = true;
$options->svgUseFillAttributes = false; // Use CSS classes
$options->drawCircularModules = true; // Circular modules
$options->circleRadius = 0.4; // Circle size (0.1-0.75)
$options->connectPaths = true; // Connect paths for smaller SVG
$options->keepAsSquare = [ // Keep finder patterns square
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
];
// Add SVG definitions for gradients and styles
$options->svgDefs = '
';
try {
$svg = (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
header('Content-Type: image/svg+xml');
if (extension_loaded('zlib')) {
header('Vary: Accept-Encoding');
header('Content-Encoding: gzip');
echo gzencode($svg, 9);
} else {
echo $svg;
}
} catch (Throwable $e) {
exit($e->getMessage());
}
```
## Generate QR Code with Custom Module Colors
Create a colorful QR Code with individual colors for each module type (finder, timing, data, etc.).
```php
version = 7;
$options->outputInterface = QRGdImagePNG::class;
$options->scale = 20;
$options->outputBase64 = false;
$options->bgColor = [200, 150, 200]; // Purple background
$options->imageTransparent = true;
$options->drawCircularModules = true;
$options->drawLightModules = true;
$options->circleRadius = 0.4;
$options->keepAsSquare = [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
];
// Custom colors for each module type [R, G, B]
$options->moduleValues = [
// Finder patterns (corner squares)
QRMatrix::M_FINDER_DARK => [0, 63, 255], // Blue
QRMatrix::M_FINDER_DOT => [0, 63, 255],
QRMatrix::M_FINDER => [233, 233, 233], // Light gray
// Alignment patterns
QRMatrix::M_ALIGNMENT_DARK => [255, 0, 255], // Magenta
QRMatrix::M_ALIGNMENT => [233, 233, 233],
// Timing patterns
QRMatrix::M_TIMING_DARK => [255, 0, 0], // Red
QRMatrix::M_TIMING => [233, 233, 233],
// Format information
QRMatrix::M_FORMAT_DARK => [67, 159, 84], // Green
QRMatrix::M_FORMAT => [233, 233, 233],
// Version information
QRMatrix::M_VERSION_DARK => [62, 174, 190], // Cyan
QRMatrix::M_VERSION => [233, 233, 233],
// Data modules
QRMatrix::M_DATA_DARK => [0, 0, 0], // Black
QRMatrix::M_DATA => [233, 233, 233],
// Dark module
QRMatrix::M_DARKMODULE => [0, 0, 0],
// Separator
QRMatrix::M_SEPARATOR => [233, 233, 233],
// Quiet zone
QRMatrix::M_QUIETZONE => [233, 233, 233],
];
$output = (new QRCode($options))->render('https://www.example.com');
header('Content-Type: image/png');
echo $output;
```
## Generate Multi-Mode QR Code
Create QR codes with mixed encoding modes for optimized data storage (numeric, alphanumeric, byte, Kanji, Hanzi).
```php
outputBase64 = false;
$options->connectPaths = true; // Optimize SVG paths
// Build QR code with multiple encoding modes
$qrcode = (new QRCode($options))
->addNumericSegment('1312') // Numeric mode
->addByteSegment("\n") // Byte mode
->addAlphaNumSegment('ACAB') // Alphanumeric mode
->addByteSegment("\n")
->addKanjiSegment('すべての警官はろくでなしです') // Kanji mode (Japanese)
->addByteSegment("\n")
->addHanziSegment('所有警察都是混蛋') // Hanzi mode (Chinese)
->addByteSegment("\n")
->addByteSegment('https://www.example.com/path')
;
$svg = $qrcode->render();
header('Content-Type: image/svg+xml');
if (extension_loaded('zlib')) {
header('Vary: Accept-Encoding');
header('Content-Encoding: gzip');
echo gzencode($svg, 9);
} else {
echo $svg;
}
```
## Generate QR Code with Logo Space
Create a QR Code with a reserved space in the center for embedding a logo image.
```php
options->returnResource = true;
if (!is_file($logo) || !is_readable($logo)) {
throw new QRCodeOutputException('Invalid logo file');
}
// Generate QR code base
parent::dump($file);
// Load logo image
$im = imagecreatefrompng($logo);
if ($im === false) {
throw new QRCodeOutputException('Failed to load logo PNG');
}
// Get logo dimensions
$w = imagesx($im);
$h = imagesy($im);
// Calculate scaled logo size (leave 1 module border)
$lw = (($this->options->logoSpaceWidth - 2) * $this->options->scale);
$lh = (($this->options->logoSpaceHeight - 2) * $this->options->scale);
// Get QR code size
$ql = ($this->matrix->getSize() * $this->options->scale);
// Copy and scale logo onto QR code (centered)
imagecopyresampled(
$this->image, $im,
(($ql - $lw) / 2), (($ql - $lh) / 2),
0, 0,
$lw, $lh,
$w, $h
);
$imageData = $this->dumpImage();
$this->saveToFile($imageData, $file);
if ($this->options->outputBase64) {
$imageData = $this->toBase64DataURI($imageData);
}
return $imageData;
}
}
// Configuration with logo space
$options = new QROptions;
$options->version = 5;
$options->outputBase64 = false;
$options->scale = 6;
$options->imageTransparent = false;
$options->drawCircularModules = true;
$options->circleRadius = 0.45;
$options->keepAsSquare = [
QRMatrix::M_FINDER,
QRMatrix::M_FINDER_DOT,
];
$options->eccLevel = EccLevel::H; // High ECC required for logo
$options->addLogoSpace = true; // Reserve logo space
$options->logoSpaceWidth = 13; // Logo width in modules
$options->logoSpaceHeight = 13; // Logo height in modules
try {
$qrcode = new QRCode($options);
$qrcode->addByteSegment('https://github.com');
$qrOutputInterface = new QRImageWithLogo($options, $qrcode->getQRMatrix());
$output = $qrOutputInterface->dump(null, __DIR__ . '/logo.png');
header('Content-Type: image/png');
echo $output;
} catch (Throwable $e) {
error_log('Logo QR generation failed: ' . $e->getMessage());
exit('Error generating QR code with logo');
}
```
## Generate Console/Text QR Code
Output QR codes as ASCII/ANSI art for command-line interfaces.
```php
version = 5;
$options->outputInterface = QRStringText::class;
$options->eol = "\n";
// Simple block characters
$options->moduleValues = [
QRMatrix::M_DATA_DARK => '██', // Dark module
QRMatrix::M_DATA => '░░', // Light module
];
$text = (new QRCode($options))->render('https://github.com/chillerlan');
echo $text;
// Advanced: Use ANSI color codes
$options->moduleValues = [
QRMatrix::M_FINDER_DARK => QRStringText::ansi8(231, true), // Bright white on black
QRMatrix::M_FINDER_DOT => QRStringText::ansi8(231, true),
QRMatrix::M_ALIGNMENT_DARK => QRStringText::ansi8(93, true), // Magenta
QRMatrix::M_TIMING_DARK => QRStringText::ansi8(200, true), // Pink
QRMatrix::M_FORMAT_DARK => QRStringText::ansi8(88, true), // Red
QRMatrix::M_VERSION_DARK => QRStringText::ansi8(28, true), // Green
QRMatrix::M_DATA_DARK => QRStringText::ansi8(232, true), // Dark
QRMatrix::M_DARKMODULE => QRStringText::ansi8(162, true), // Orange
QRMatrix::M_DATA => QRStringText::ansi8(255, false), // Light
];
$coloredText = (new QRCode($options))->render('https://github.com/chillerlan');
echo $coloredText;
```
## Read/Decode QR Code from File
Decode QR codes from image files with preprocessing options for better recognition.
```php
readerUseImagickIfAvailable = false; // Use GD instead of ImageMagick
$options->readerGrayscale = true; // Convert to grayscale
$options->readerIncreaseContrast = true; // Increase contrast
$options->readerInvertColors = false; // Don't invert colors
try {
$qrcode = new QRCode($options);
$result = $qrcode->readFromFile('/path/to/qrcode.png');
// Access decoded data
echo "Decoded content: " . $result->data . "\n";
echo "QR Version: " . $result->version->getVersionNumber() . "\n";
echo "ECC Level: " . $result->eccLevel->getLevel() . "\n";
echo "Mask Pattern: " . $result->maskPattern->getPattern() . "\n";
// Check for structured append (multi-part QR codes)
if ($result->hasStructuredAppend()) {
echo "Structured append sequence: " . $result->structuredAppendSequence . "\n";
echo "Structured append parity: " . $result->structuredAppendParity . "\n";
}
// Get the QR matrix for further processing
$matrix = $result->getQRMatrix();
echo "Matrix size: " . $matrix->getSize() . "x" . $matrix->getSize() . "\n";
} catch (Throwable $e) {
error_log("QR decode error: " . $e->getMessage());
echo "Failed to decode QR code: " . $e->getMessage() . "\n";
}
```
## Read QR Code from Binary Data
Decode QR codes directly from image binary data or blob.
```php
readerUseImagickIfAvailable = true;
$options->readerGrayscale = true;
$options->readerIncreaseContrast = true;
$qrcode = new QRCode($options);
// Read from uploaded file
if (isset($_FILES['qrcode']) && $_FILES['qrcode']['error'] === UPLOAD_ERR_OK) {
try {
$imageBlob = file_get_contents($_FILES['qrcode']['tmp_name']);
$result = $qrcode->readFromBlob($imageBlob);
echo json_encode([
'success' => true,
'data' => $result->data,
'version' => $result->version->getVersionNumber(),
'eccLevel' => $result->eccLevel->getLevel(),
]);
} catch (Throwable $e) {
echo json_encode([
'success' => false,
'error' => $e->getMessage(),
]);
}
}
// Read from HTTP request body (API endpoint)
$imageBlob = file_get_contents('php://input');
if (!empty($imageBlob)) {
try {
$result = $qrcode->readFromBlob($imageBlob);
header('Content-Type: application/json');
echo json_encode([
'decoded' => $result->data,
'metadata' => [
'version' => $result->version->getVersionNumber(),
'eccLevel' => $result->eccLevel->getLevel(),
'maskPattern' => $result->maskPattern->getPattern(),
],
]);
} catch (Throwable $e) {
http_response_code(400);
echo json_encode(['error' => 'Invalid QR code: ' . $e->getMessage()]);
}
}
```
## Generate QR Code with ECI Encoding
Create QR codes with Extended Channel Interpretation for specific character encodings.
```php
outputBase64 = false;
// Add ECI designator for UTF-8 encoding
$qrcode = (new QRCode($options))
->addEciDesignator(ECICharset::UTF8) // ECI 26 = UTF-8
->addByteSegment('Привет мир') // Russian text
->addByteSegment("\n")
->addByteSegment('مرحبا بالعالم') // Arabic text
;
$svg = $qrcode->render();
echo $svg;
// Alternative: Use addEciSegment for encoding + data
$qrcode2 = (new QRCode($options))
->addEciSegment(ECICharset::UTF8, 'Καλημέρα κόσμε') // Greek
->addByteSegment("\n")
->addEciSegment(ECICharset::UTF8, 'שלום עולם') // Hebrew
;
$svg2 = $qrcode2->render();
```
## Generate PDF QR Code with FPDF
Create QR codes in PDF documents using the FPDF library.
```php
version = 5;
$options->outputInterface = QRFpdf::class;
$options->fpdfMeasureUnit = 'mm'; // pt, mm, cm, in
$options->scale = 5;
$options->bgColor = [255, 255, 255];
$options->moduleValues = [
// Custom colors for PDF output [R, G, B]
1024 => [0, 0, 0], // Dark modules
4 => [255, 255, 255], // Light modules
];
try {
$qrcode = new QRCode($options);
$pdfData = $qrcode->render('https://www.example.com/pdf-document');
// Output PDF to browser
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="qrcode.pdf"');
echo $pdfData;
// Or save to file
file_put_contents('qrcode.pdf', $pdfData);
} catch (Throwable $e) {
exit('PDF generation failed: ' . $e->getMessage());
}
```
## Generate JSON QR Code Matrix
Export the QR code matrix as JSON data for custom processing.
```php
version = 5;
$options->outputInterface = QRStringJSON::class;
$options->jsonFlags = JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT;
try {
$qrcode = new QRCode($options);
$json = $qrcode->render('https://api.example.com/endpoint');
// Parse the JSON matrix
$matrix = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
echo "Matrix size: " . count($matrix) . "x" . count($matrix[0]) . "\n";
echo "JSON output:\n" . $json . "\n";
// Process matrix data
foreach ($matrix as $y => $row) {
foreach ($row as $x => $module) {
// $module contains the module type value (e.g., 1024 for dark data)
if ($module === 1024) { // Dark data module
// Process dark module at position [$y][$x]
}
}
}
// Use in API response
header('Content-Type: application/json');
echo json_encode([
'qrcode' => $matrix,
'size' => count($matrix),
'data' => 'https://api.example.com/endpoint',
], JSON_THROW_ON_ERROR);
} catch (Throwable $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
```
## Generate HTML Table QR Code
Create QR codes as HTML tables with CSS styling for web integration.
```php
version = 5;
$options->outputInterface = QRMarkupHTML::class;
$options->cssClass = 'my-qrcode';
$options->moduleValues = [
// CSS class names for different module types
QRMatrix::M_FINDER_DARK => 'finder',
QRMatrix::M_FINDER_DOT => 'finder-dot',
QRMatrix::M_ALIGNMENT_DARK => 'alignment',
QRMatrix::M_TIMING_DARK => 'timing',
QRMatrix::M_FORMAT_DARK => 'format',
QRMatrix::M_VERSION_DARK => 'version',
QRMatrix::M_DATA_DARK => 'data',
QRMatrix::M_DARKMODULE => 'dark',
];
$html = (new QRCode($options))->render('https://www.example.com');
// Output with custom CSS
?>
```
## Advanced Configuration Example
Comprehensive example showing all major configuration options.
```php
version = Version::AUTO; // 1-40 or AUTO
$options->versionMin = 1; // Min version for AUTO
$options->versionMax = 10; // Max version for AUTO
$options->eccLevel = EccLevel::Q; // L (7%), M (15%), Q (25%), H (30%)
$options->maskPattern = MaskPattern::AUTO; // 0-7 or AUTO
// Quiet Zone (Margin)
$options->addQuietzone = true;
$options->quietzoneSize = 4; // Modules
// Output Configuration
$options->outputInterface = QRMarkupSVG::class;
$options->returnResource = false;
$options->cachefile = null; // Save to file path
$options->outputBase64 = true; // Data URI for images
$options->eol = PHP_EOL;
// Visual Modifications
$options->bgColor = [255, 255, 255]; // Background color RGB
$options->invertMatrix = false; // Invert dark/light
$options->drawLightModules = true; // Render light modules
$options->drawCircularModules = false; // Circles vs squares
$options->circleRadius = 0.45; // 0.1-0.75
$options->connectPaths = false; // Connect SVG paths
$options->keepAsSquare = []; // Module types to keep square
// Logo Space
$options->addLogoSpace = false;
$options->logoSpaceWidth = null;
$options->logoSpaceHeight = null;
$options->logoSpaceStartX = null; // Auto-center if null
$options->logoSpaceStartY = null;
// Raster Image Settings (GD)
$options->scale = 5; // Pixels per module
$options->imageTransparent = false;
$options->transparencyColor = null; // RGB color to make transparent
$options->quality = -1; // Compression quality (0-100)
$options->gdImageUseUpscale = true;
// SVG Settings
$options->cssClass = 'qrcode';
$options->svgAddXmlHeader = true;
$options->svgDefs = ''; // SVG content
$options->svgPreserveAspectRatio = 'xMidYMid';
$options->svgUseFillAttributes = true; // Fill attrs vs CSS
// Reader Settings
$options->readerUseImagickIfAvailable = false;
$options->readerGrayscale = false;
$options->readerInvertColors = false;
$options->readerIncreaseContrast = false;
try {
$qrcode = new QRCode($options);
$output = $qrcode->render('Fully configured QR code');
echo $output;
} catch (Throwable $e) {
exit('Configuration error: ' . $e->getMessage());
}
```
## Summary
chillerlan/php-qrcode provides a complete solution for QR code generation and reading in PHP applications. The library's main use cases include creating QR codes for URLs, product tracking, payment systems, authentication (TOTP), contact information (vCard), WiFi credentials, and document verification. It supports high-volume generation through optimized encoding modes and can produce QR codes in any required format from web-ready SVGs and PNGs to print-ready PDFs and EPS files. The reader functionality enables applications to decode QR codes from uploaded images, camera captures, or scanned documents with preprocessing options for challenging lighting conditions.
Integration patterns typically involve creating a QROptions instance with desired settings, instantiating the QRCode class, and calling render() for generation or readFromFile()/readFromBlob() for decoding. Advanced use cases include custom output classes extending QROutputInterface for specialized rendering (logos, watermarks, custom shapes), multi-mode encoding for international content mixing Kanji/Hanzi/Latin scripts, and matrix manipulation for adding custom graphical elements. The library integrates seamlessly with popular frameworks (Laravel, Symfony, WordPress, Drupal) and supports both synchronous generation and batch processing with file caching. Error handling follows PHP best practices with exceptions for all failure scenarios, making it production-ready for mission-critical applications requiring reliable QR code functionality.