yoosuf / qr
Fast and extensible Laravel QR code generation with typed payload builders, CLI automation, and performance-focused rendering.
Requires
- php: ^8.1
- bacon/bacon-qr-code: ^3.0
- illuminate/support: ^10.0|^11.0|^12.0
README
Fast, extensible QR code generation for Laravel apps and automation workflows.
Generate standards-compliant QR payloads, style them for brand needs, and produce output through PHP APIs or CLI with a performance-oriented architecture.
Why this package
- Laravel-native integration with auto-discovery, facade, and helper.
- Pluggable style architecture for presets, custom modules, custom eyes, and custom drivers.
- Typed payload builders for URL, Wi-Fi, vCard, MECARD, email, SMS, geo, calendar event, WhatsApp, bitcoin, and raw text.
- Bacon-backed rendering with SVG, PNG, and EPS output options.
- Option merging that keeps defaults, profiles, driver config, and runtime overrides separate.
- Hot-path performance improvements through in-memory writer reuse and optional result caching.
Installation
composer require yoosuf/qr
Publish the configuration if needed.
php artisan vendor:publish --tag=qr-config
Documentation
- CLI usage guide: docs/CLI.md
- Architecture guide: docs/ARCHITECTURE.md
- Product report (topics and descriptions): docs/REPORT.md
Best Fit Use Cases
- checkout and payment QR generation
- event ticket and check-in flows
- contact card and profile sharing
- Wi-Fi onboarding for venues and offices
- batch QR rendering in queues and CI pipelines
Quick Start
use Yoosuf\Qr\Facades\Qr; $svg = Qr::render('SO-1001')->contents; $dataUri = Qr::dataUri('SO-1001', 'svg', [ 'profile' => 'brand', ]); $storedPath = Qr::save('qr/so-1001.svg', 'SO-1001');
Typed payloads (all common QR content standards)
Pass raw strings, payload arrays, or QrPayload objects.
use Yoosuf\Qr\Facades\Qr; use Yoosuf\Qr\Support\QrPayload; $wifi = QrPayload::wifi('Office-5G', 'super-secret-password', 'WPA2', false); $vcard = QrPayload::vcard([ 'first_name' => 'Yoosuf', 'last_name' => 'A', 'organization' => 'Nord', 'title' => 'Engineer', 'phone' => '+9607000000', 'email' => 'yoosuf@example.com', 'url' => 'https://example.com', ]); $svgWifi = Qr::render($wifi)->contents; $svgContact = Qr::render($vcard)->contents; // Array payload syntax also works $sms = Qr::render([ 'type' => 'sms', 'number' => '+9607000000', 'message' => 'Hello from QR', ]);
Supported payload type values:
raw,text,stringurl,linkphone,telsmsemail,mailtogeo,locationwifivcardmecardevent,veventwhatsapp,wabitcoin,btc
Add your own payload type without touching package internals:
qr()->extendPayload('upi', function (array $payload): string { $vpa = $payload['vpa'] ?? ''; $name = $payload['name'] ?? ''; return 'upi://pay?pa='.rawurlencode((string) $vpa).'&pn='.rawurlencode((string) $name); });
Extending the design system
The package is built around two extension points:
- custom QR modules, such as rounded or branded module groups;
- custom QR eyes, such as circles, points, or fully bespoke finder patterns.
Register custom shapes through the manager and continue using the same rendering API.
qr()->extendModule('hex', function (string $name, array $options) { return \BaconQrCode\Renderer\Module\SquareModule::instance(); });
Output formats
svgfor portable vector output.pngwhen theimagickextension is available.epsfor print-oriented workflows.
CLI generation
For full command reference and examples, see docs/CLI.md.
Generate QR codes directly from Artisan:
php artisan qr:generate "SO-1001" --driver=svg --path=qr/so-1001.svg
When using the default local disk, --path is relative to the disk root (storage/app).
Passing storage/app/... is also accepted and normalized automatically.
Generate with typed payload JSON:
php artisan qr:generate --payload='{"type":"wifi","ssid":"Office-5G","password":"secret","encryption":"WPA2"}' --driver=svg --path=qr/wifi.svg
Print output to terminal (SVG text by default):
php artisan qr:generate "https://example.com" --driver=svg
Print as data URI:
php artisan qr:generate "https://example.com" --data-uri
Pass rendering options from CLI (--option can be repeated and supports nested keys):
php artisan qr:generate "SO-1001" \ --driver=svg \ --path=qr/so-1001-brand.svg \ --option=profile=brand \ --option=size=512 \ --option=foreground_gradient.type=diagonal \ --option=foreground_gradient.start_color=#0f172a \ --option=foreground_gradient.end_color=#0ea5e9
Performance tuning
Enable package-level result caching for repeated payloads and options:
// config/qr.php 'cache' => [ 'enabled' => true, 'store' => 'redis', 'ttl' => 3600, 'prefix' => 'qr', ],
What is optimized:
- renderer/writer instances are reused in-memory for equivalent style options;
- error correction objects are reused in-memory;
- merged options are memoized in the manager;
- final rendered bytes can be cached through Laravel cache stores.