bacon/bacon-qr-code
PHP QR code generator ported from ZXing (encoder only). Render to PNG via Imagick, or output SVG/EPS; includes a separate GDLib renderer. Simple Writer API to generate QR codes to files or strings.
Installation:
composer require bacon/bacon-qr-code
Basic Usage (GDLib for simplicity):
use BaconQrCode\Writer;
use BaconQrCode\Renderer\GDLibRenderer;
$writer = new Writer(new GDLibRenderer(400)); // 400px size
$writer->writeFile('Hello World!', 'qrcode.png');
Key Classes:
Writer: Main entry point for QR generation.Renderer: Abstract base for output formats (e.g., GDLibRenderer, ImageRenderer).RendererStyle: Configures QR appearance (size, colors, etc.).Generate a QR code for a user profile link in a Laravel controller:
use BaconQrCode\Writer;
use BaconQrCode\Renderer\GDLibRenderer;
public function generateProfileQr(User $user)
{
$writer = new Writer(new GDLibRenderer(300));
$writer->writeFile(
route('profile.show', $user),
storage_path("app/qr_{$user->id}.png")
);
return response()->download(storage_path("app/qr_{$user->id}.png"));
}
public function generateOrderQr(Order $order)
{
$writer = new Writer(
new GDLibRenderer(350, 'black', 'white')
);
$writer->writeFile(
route('orders.show', $order),
storage_path("app/qr_orders/{$order->id}.png")
);
}
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\Image\SvgImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
$renderer = new ImageRenderer(
new RendererStyle(500, 'black', 'transparent'),
new SvgImageBackEnd()
);
$writer = new Writer($renderer);
$writer->writeFile('https://example.com', 'qrcode.svg');
public function batchGenerateQrCodes(array $items)
{
$writer = new Writer(new GDLibRenderer(250));
foreach ($items as $item) {
$writer->writeFile(
"item:{$item->id}",
"public/qr_{$item->id}.png"
);
}
}
use Illuminate\Support\Facades\Storage;
public function generateAndStoreQr($content, $filename)
{
$writer = new Writer(new GDLibRenderer(400));
$writer->writeFile($content, storage_path("app/{$filename}.png"));
Storage::disk('s3')->put("qrcodes/{$filename}.png", file_get_contents(storage_path("app/{$filename}.png")));
}
use BaconQrCode\Writer;
use BaconQrCode\Renderer\GDLibRenderer;
use BaconQrCode\Writer\WriterOptions;
$options = new WriterOptions();
$options->setErrorCorrectionLevel(WriterOptions::ERROR_CORRECTION_LEVEL_HIGH);
$writer = new Writer(new GDLibRenderer(400), $options);
$writer->writeFile('High-error-content', 'qrcode_high.png');
Register a QR code generator as a singleton:
public function register()
{
$this->app->singleton('qrcode.generator', function () {
return new Writer(new GDLibRenderer(400));
});
}
Create a custom Blade directive for inline QR generation:
Blade::directive('qrcode', function ($expression) {
$content = $expression;
$filename = 'temp_qr_' . Str::random(10) . '.png';
$writer = app('qrcode.generator');
$writer->writeFile($content, storage_path("app/{$filename}"));
return "<?php echo '<img src=\"' . asset('storage/{$filename}') . '\" alt=\"QR Code\">'; ?>";
});
Usage in Blade:
@qrcode(route('profile.show', $user))
Return QR codes as downloadable responses:
public function downloadQr($content)
{
$writer = new Writer(new GDLibRenderer(300));
$writer->writeFile($content, storage_path('app/qr_temp.png'));
return response()->download(storage_path('app/qr_temp.png'))
->deleteFileAfterSend(true);
}
Validate QR content in form requests:
public function rules()
{
return [
'qr_content' => [
'required',
function ($attribute, $value, $fail) {
// Validate content length (QR codes have limits)
if (strlen($value) > 2953) {
$fail('The QR code content may not be greater than 2953 characters.');
}
},
],
];
}
ImagickImageBackEnd may produce white pixel artifacts (especially with margin=0).SvgImageBackEnd or GDLibRenderer for artifact-free output.// Avoid Imagick for critical use cases
$renderer = new ImageRenderer(
new RendererStyle(400),
new SvgImageBackEnd() // No artifacts
);
GDLibRenderer does not support gradients or curved edges (always squared).ImageRenderer with ImagickImageBackEnd or SvgImageBackEnd for advanced features.// Use GD only for simple, squared QR codes
$renderer = new GDLibRenderer(400, 'black', 'white');
SvgImageBackEnd requires the xmlwriter extension.if (!extension_loaded('xmlwriter')) {
throw new \RuntimeException('The xmlwriter extension is required for SVG rendering.');
}
GDLibRenderer or ImagickImageBackEnd if xmlwriter is unavailable.use BaconQrCode\Writer\WriterOptions;
$options = new WriterOptions();
if (strlen($content) > 2953) {
$options->setMode(WriterOptions::MODE_BYTE);
}
storage/app may fail due to permissions.chmod -R 775 storage/
storage_path() with proper permissions or a dedicated directory.public function getQrCode($content)
{
$hash = md5($content);
$path = storage_path("app/qr_cache/{$hash}.png");
if (!file_exists($path)) {
$writer = new Writer(new GDLibRenderer(400));
$writer->writeFile($content, $path);
}
return response()->file($path);
}
$writer->writeFile('test', 'debug_qr.png');
if (file_exists('debug_q
How can I help you explore Laravel packages today?