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 Laravel Package

wolfcode/bacon-qr-code

Laravel wrapper for BaconQrCode that makes generating QR codes simple. Create customizable QR codes as SVG or PNG, save them to disk, or return them directly from controllers with a clean, expressive API. Supports size, margin, error correction, and colors.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require wolfcode/bacon-qr-code

This is a fork of the BaconQrCode library, so the namespace is still BaconQrCode\. There is no service provider — it is a plain PHP library you instantiate yourself. Requirements:

  • PHP 8.1+ (check the fork's composer.json; upstream requires ^7.4|^8.0)
  • ext-imagick only if you want PNG output. SVG and EPS backends are pure PHP.

Where to look first:

  1. src/Renderer/ImageRenderer.php — the main renderer
  2. src/Renderer/Image/* — available backends (SvgImageBackEnd, ImagickImageBackEnd, EpsImageBackEnd)
  3. src/Renderer/RendererStyle/RendererStyle.php — sizing/margin/ECC controls
  4. src/Writer.php — the entry point (writeString, writeFile)

First use case — return a QR as SVG from a route:

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

Route::get('/qr', function () {
    $renderer = new ImageRenderer(
        new RendererStyle(300),
        new SvgImageBackEnd()
    );

    $svg = (new Writer($renderer))->writeString('https://example.com');

    return response($svg, 200, ['Content-Type' => 'image/svg+xml']);
});

If that route renders, you have everything you need to move on to the patterns below.

Implementation Patterns

Wrap it in a small service so you never repeat the boilerplate. Bind it in a provider:

// app/Services/QrCodeService.php
namespace App\Services;

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

class QrCodeService
{
    public function svg(string $data, int $size = 300, int $margin = 0): string
    {
        $renderer = new ImageRenderer(
            new RendererStyle($size, $margin),
            new SvgImageBackEnd()
        );

        return (new Writer($renderer))->writeString($data);
    }

    public function png(string $data, int $size = 300, int $margin = 0): string
    {
        $renderer = new ImageRenderer(
            new RendererStyle($size, $margin),
            new ImagickImageBackEnd('png')
        );

        return (new Writer($renderer))->writeString($data);
    }
}
// app/Providers/AppServiceProvider.php
$this->app->singleton(\App\Services\QrCodeService::class);

Inline image in Blade (SVG as data URI):

<img src="data:image/svg+xml;base64,{{ base64_encode(app(QrCodeService::class)->svg($url)) }}" alt="QR">

Base64 encoding avoids the XML declaration and any < characters leaking into your HTML.

Downloadable PNG:

public function download(Request $request, QrCodeService $qr)
{
    $png = $qr->png($request->input('url'), 600, 0);

    return response($png, 200, [
        'Content-Type'        => 'image/png',
        'Content-Disposition' => 'attachment; filename="qr.png"',
    ]);
}

Write straight to storage (skip the string round-trip for large sizes):

$writer = new Writer(
    new ImageRenderer(new RendererStyle(1024), new ImagickImageBackEnd('png'))
);
$writer->writeFile($url, storage_path('app/public/qr.png'));

Higher error correction for printed/sticker QR codes — pass an ErrorCorrectionLevel to RendererStyle:

use BaconQrCode\Common\ErrorCorrectionLevel;

new RendererStyle($size, $margin, null, null, ErrorCorrectionLevel::H())

Use L for dense URLs you want to keep small, H for logos/labels where part of the code will be obscured.

Cache the rendered bytes — generation is cheap but not free, and SVG output is highly compressible:

return Cache::remember("qr:{$hash}", now()->addDay(), fn () => $qr->svg($url));

Route model integration — treat a QR as a resource endpoint so you can scope authorization and logging:

Route::get('/events/{event}/qr.svg', [QrController::class, 'show'])->name('events.qr');

This lets you use Gate/Policy on the underlying model before generating the code, which is the correct pattern for anything short-lived or tokenized.

Gotchas and Tips

PNG requires Imagick, not GD. ImagickImageBackEnd will throw at runtime if ext-imagick is missing. Check extension_loaded('imagick') in a deployment health check or fall back to SVG. Many shared hosts disable Imagick; if so, ship SVG and let CSS scale it.

The package name and namespace differ. You install wolfcode/bacon-qr-code, but use BaconQrCode\.... If anything else in the tree pulls in bacon/bacon-qr-code (e.g. simplesoftwareio/simple-qrcode), composer may install both and you'll get confusing "class not found" or duplicate-class behaviour. Run composer why bacon/bacon-qr-code if you see oddities, and prefer one dependency chain.

It's a fork with 0 stars and no dependents. Pin the version in composer.json ("wolfcode/bacon-qr-code": "2.*") and treat upgrades as a manual review step — there's no ecosystem signal that will warn you about regressions. If you only need SVG, consider evaluating upstream bacon/bacon-qr-code directly, since it has the maintenance and security history.

RendererStyle size is a request, not a guarantee. The renderer adjusts to a whole number of modules. Asking for size 100 with a long URL and ECC level H produces a code with tiny, unreadable modules. Validate: keep size ≥ 200 for content longer than ~50 chars, and don't let users pick arbitrary sizes without a floor.

Guard against unbounded input. A user-supplied URL plus a user-supplied size=10000 is a trivial memory DoS with Imagick. Clamp both:

$size = min(max((int) $request->integer('size', 300), 100), 1024);

Long data throws. Oversized payloads exceed QR capacity and throw BaconQrCode\Exception\RuntimeException. Catch it and return a 422 rather than surfacing a 500:

try {
    $svg = $qr->svg($data);
} catch (\BaconQrCode\Exception\RuntimeException $e) {
    abort(422, 'Content too long for a QR code.');
}

Use RendererStyle($size, $margin) deliberately. The default margin is 4 modules (the QR spec's "quiet zone"). Setting it to 0 makes codes look tight in UIs but can hurt scan reliability on printed media — keep at least 1–2 for anything physical.

SVG output starts with <?xml ... ?>. If you inject it directly into HTML (not via <img>), browsers may or may not honor it depending on the parser path. Always serve it with Content-Type: image/svg+xml or as a data URI, never as a fragment inside a text/html document.

Encoding/ECI. writeString($data) assumes a default encoding. For non-ASCII payloads (emoji, CJK), pass the encoding argument ($writer->writeString($data, 'UTF-8')) so scanners decode consistently, and verify with a physical scanner — automated tests won't catch a bad ECI flag.

No Blade component ships with the package. If you want <x-qr-code :data="$url" />, build it yourself around the service above; don't expect the fork to ship one.

Testing tip. Don't assert on rendered pixels. Assert on the string prefix (<svg for SVG, \x89PNG for PNG) and on throw behaviour for oversized input. If you need to verify scannability, decode with a separate library in an integration test rather than eyeballing snapshots.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect