Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Bacon Qr Code Bundle Laravel Package

tourze/bacon-qr-code-bundle

Symfony bundle that integrates the BaconQrCode library into your application, making it easy to generate QR codes from PHP. Provides service configuration and helpers so you can create SVG or PNG QR codes for URLs, text, and more with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

tourze/bacon-qr-code-bundle is a thin Symfony bundle around bacon/bacon-qr-code: it registers the encoder/writer/renderer as container services and exposes a small config surface for RendererStyle. The QR logic itself is 100% upstream, so the practical on-ramp is: install it, then read two directories.

composer require tourze/bacon-qr-code-bundle:^0.1
  1. vendor/tourze/bacon-qr-code-bundle/src/ — find the *Bundle class, DependencyInjection/*Extension.php, and Resources/config/services.yaml. That is the entire value-add: which service IDs exist and what parameters the config maps to.
  2. vendor/bacon/bacon-qr-code/src/ — Writer, Encoder, Renderer\ImageRenderer, Renderer\Image\*, Renderer\RendererStyle\*. This is where you will actually spend your time.

First use case: a 2FA enrollment screen or a signed short-URL. Render SVG — it needs no image extension and scales cleanly.

use BaconQrCode\Renderer\Image\SvgImageBackEnd;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
use BaconQrCode\Writer;

$writer = new Writer(new ImageRenderer(new RendererStyle(400, 2), new SvgImageBackEnd()));

return view('auth.qr', ['svg' => $writer->writeString($user->twoFactorOtpauthUri())]);

Bind it once in a service provider rather than constructing per request:

// app/Providers/QrCodeServiceProvider.php
$this->app->singleton(Writer::class, fn () => new Writer(
    new ImageRenderer(
        new RendererStyle(config('qr.size'), config('qr.margin')),
        new SvgImageBackEnd()
    )
));

Note up front: because this is a Symfony bundle rather than a Laravel package, there is no vendor:publish config and no auto-discovery. You are writing that provider yourself — the bundle is a reference implementation for the defaults, not a Laravel integration.

Implementation Patterns

Wrap the writer, don't sprinkle it. Put a single QrCodeService (or a QrCode value object with toSvg() / toDataUri()) in front of the Writer. Controllers and Blade templates should never see RendererStyle. This also gives you one place to change backend (SVG in dev, PNG in prod) and one place to add caching.

Response strategies, in order of preference:

// Inline SVG — cheapest, no extensions
return response($svg, 200, ['Content-Type' => 'image/svg+xml']);

// PNG — requires ext-imagick
return response($writer->writeString($payload), 200, ['Content-Type' => 'image/png']);

// Inline in HTML
<img src="data:image/svg+xml;base64,{{ base64_encode($svg) }}" alt="QR code">

Config-driven style. Mirror whatever the bundle's extension exposes into config/qr.php (size, margin, foreground/background Rgb). Keep default error correction at ErrorCorrectionLevel::M and only raise to Q/H when you overlay a logo or expect a damaged print.

Cache by payload hash. Encoding is pure: cache()->remember('qr:'.hash('xxh128', $payload), now()->addDay(), fn () => $writer->writeString($payload)). Add an ETag from the same hash so repeat scans get 304s. If you generate QR codes in bulk (batch of signed labels), pre-generate on a queue and store the artifact — do not do it inside the request.

Testing. Assert on the shape of the output, not the pixel data: assertStringStartsWith('<svg', $svg), or decode the PNG header for the expected dimensions. A full-string snapshot will churn on every upstream patch release.

Integration with 2FA. The QR payload is just the otpauth:// URI produced by Fortify / pragmarx/google2fa. Keep those libraries responsible for the URI and this one responsible for pixels; don't let the QR layer build secrets.

If you also run a Symfony app in the same monorepo, that is where the bundle earns its keep: register BaconQrCodeBundle in bundles.php, and the Writer is injected for you. In a pure Laravel app, treat the bundle as documentation and depend on bacon/bacon-qr-code directly.

Gotchas and Tips

  • Symfony bundle, not a Laravel package. BaconQrCodeBundle extends Symfony\Component\HttpKernel\Bundle\Bundle and its extension expects a container to compile. Laravel will not autoregister it, and composer require will pull Symfony HttpKernel/DependencyInjection into your vendor/. If you only want QR codes, requiring bacon/bacon-qr-code alone is the smaller dependency.
  • No changelog for 0.1.0. The release note is a bare compare/0.0.3...0.1.0 link. Read that diff before upgrading. Under semver, 0.x minor bumps are allowed to break; pin 0.1.* or an exact version in composer.json and let a human review the bump.
  • PNG needs ext-imagick. ImagickImageBackEnd will blow up with a class-not-found if the extension is missing. Default to SvgImageBackEnd in code and feature-detect (extension_loaded('imagick')) before offering a PNG download route.
  • ext-iconv/mbstring for non-ASCII. QR byte-mode encoding converts the payload; non-ASCII content (emoji, CJK) needs the mbstring/iconv path and Encoding::UTF_8 passed explicitly. Silently mangled payloads scan as garbage — test with a real Japanese or emoji string if your tenants use them.
  • Data too long throws. Writer::writeString() raises WriterException when the payload exceeds the version's capacity at the chosen EC level. Catch it and return a validation error rather than a 500; URLs with long query strings hit this faster than you'd expect at level H.
  • Debugging wrong-looking output: the three knobs that matter are RendererStyle size, margin, and EC level. A QR that won't scan at small print sizes is almost always margin too small or EC too low — not a library bug. Render at 300–400px minimum for on-screen, and scale up rather than adding margin.
  • Extension points are upstream. To change colors, build RendererStyle with Rgb foreground/background. To change the image format, implement or supply an ImageBackEnd. To post-process (logo overlay, label), decorate your own Writer wrapper — do not patch vendor code, since the bundle re-exports upstream services verbatim.
  • Escape your own markup, not the QR. The SVG backend emits paths, so payload injection is not the risk. The risk is your template: the surrounding <svg> you build for logos/frames, and any alt text or <title> you interpolate. Use Blade's {{ }} there.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk