# 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 'QR Code'; // 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.