Download the PHP package devxisas/qr-studio without Composer
On this page you can find all versions of the php package devxisas/qr-studio. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download devxisas/qr-studio
More information about devxisas/qr-studio
Files in devxisas/qr-studio
Package qr-studio
Short Description A modern QR code studio for Laravel — SVG, PNG, EPS, styles, gradients, data types, Blade directive, response macro, and model traits.
License MIT
Homepage https://github.com/devxisas/qr-studio
Informations about the package qr-studio
devxisas/qr-studio
A modern QR code studio for Laravel. Inspired by and built upon the foundation of simplesoftwareio/simple-qrcode, this package brings full PHP 8.2+ type safety, enum-based APIs, new data types (vCard, MeCard, Calendar Events), a Blade directive, a response macro, a toDataUri() helper, an Artisan command, and the HasQrCode Eloquent trait — while keeping the same familiar fluent interface.
[!NOTE] Migrating from
simplesoftwareio/simple-qrcode? See the migration guide at the bottom of this page.
Requirements
| Package version | Laravel | PHP |
|---|---|---|
| 1.x | 11, 12, 13 | 8.2+ |
Installation
The service provider is registered automatically via Laravel's package auto-discovery.
PNG generation uses ext-imagick when available, and falls back to ext-gd (installed by default on most servers) when Imagick is not installed. Note: the GD fallback does not support gradients.
To install Imagick for best PNG quality:
Basic Usage
Use the QrCode facade anywhere in your application:
In a Blade template:
Configuration
Publish the config file to set package-wide defaults:
This creates config/qr-studio.php:
These defaults are applied to every QR code generated through the QrCode facade, the @qrcode Blade directive, and the response()->qrcode() macro. Per-call options always take precedence over config defaults.
| Key | Scope | Default |
|---|---|---|
format |
Global | Format::Svg |
size |
Global | 100 |
margin |
Global | 0 |
error_correction |
Global | ErrorCorrection::Medium |
encoding |
Global | 'UTF-8' |
theme |
Global | null (disabled) |
disk |
saveToDisk | 'local' |
path |
saveToDisk | 'qrcodes' |
Note:
style,eye,color,gradient, andeyeColorare always per-call — they are not configurable globally as they are visual choices that vary per use case.
Formats
Three output formats are supported. You can pass a string or the Format enum.
PNG and the GD fallback: PNG generation uses
ext-imagickwhen available. When Imagick is not installed the package falls back toext-gd. The GD fallback works for most use cases, but gradients are not supported under GD — use Imagick if you need gradient PNGs.
Size & Margin
Error Correction
Higher levels allow the QR code to be read even when partially obscured (e.g. with a logo overlay).
| Level | Enum | Data recovery |
|---|---|---|
L |
ErrorCorrection::Low |
7% |
M |
ErrorCorrection::Medium |
15% (default) |
Q |
ErrorCorrection::Quartile |
25% |
H |
ErrorCorrection::High |
30% |
Module Styles
Eye Styles
| Value | Enum | Description |
|---|---|---|
square |
EyeStyle::Square |
Default square finder eye |
circle |
EyeStyle::Circle |
Circular finder eye |
pointy |
EyeStyle::Pointy |
Curved outer corner + circle inner (BaconQrCode 3.x) |
Colors
Foreground & background
Per-eye colors
Each of the three finder eyes (0, 1, 2) can have independent inner and outer colors.
Gradients
| Type | Enum |
|---|---|
horizontal |
GradientType::Horizontal |
vertical |
GradientType::Vertical |
diagonal |
GradientType::Diagonal |
inverse_diagonal |
GradientType::InverseDiagonal |
radial |
GradientType::Radial |
Note: Gradients require
ext-imagick. They are not supported when falling back toext-gd.
Image Merging (Logo overlay)
Requires PNG format and ErrorCorrection::High (H) for reliable scanning.
The second argument is the percentage of the QR code the image should occupy (default 0.2).
Data URI (toDataUri)
Generates a base64-encoded data URI — ideal for embedding QR codes in emails, PDFs, or anywhere external URLs are unavailable.
In Blade:
Blade Directive
A @qrcode directive is registered automatically.
When no format argument is passed, the directive reads qr-studio.format from config (default svg). When no size argument is passed, the <img> width/height uses qr-studio.size from config.
SVG output is echoed directly as HTML. PNG and EPS output is wrapped in an <img src="data:..."> tag automatically so no raw binary reaches the browser.
Response Macro
Stream a QR code directly as an HTTP response with the correct Content-Type header.
When size is not passed, the macro uses qr-studio.size from config. The X-Content-Type-Options: nosniff header is always set automatically.
Artisan Command
Generate QR codes from the command line.
| Option | Default | Values |
|---|---|---|
--format |
svg |
svg, eps, png |
--size |
200 |
1–4096 |
--margin |
0 |
integer |
--error-correction |
M |
L, M, Q, H |
--output |
stdout | file path |
Data Types
All data types return an HtmlString just like generate() and follow the same fluent interface.
URL / Plain text
Phone number
SMS
Geo location
WiFi
Bitcoin
vCard 3.0
MeCard (iOS / Android)
Calendar Event (iCal)
Accepts ISO 8601 strings, Unix timestamps, or any DateTimeInterface.
Generates a wa.me deep-link QR code. Scanning it opens WhatsApp with the number pre-filled and, when a message is provided, the text pre-typed in the message box.
The phone number is normalised to digits only — international format is required (+503 → 503).
Themes
Apply a complete visual preset — colors, gradient, module style, and eye style — with a single call. Any option chained after theme() overrides the preset.
| Theme | Description |
|---|---|
ocean |
Deep blue → cyan radial gradient · dot modules · circle eyes |
sunset |
Orange → crimson diagonal gradient · square eyes |
forest |
Dark green → mint vertical gradient · round modules · square eyes |
midnight |
Light blue-white text on deep navy background |
coral |
Coral → hot-pink horizontal gradient · dot modules · circle eyes |
Note: Themes that use
dotorroundmodules automatically seterrorCorrection('H')to ensure scannability.
saveToDisk()
Save any QR code directly to a Laravel filesystem disk (local, S3, public, etc.).
Path resolution: when $filename contains no /, the path from config is prepended automatically ('qr.png' → 'qrcodes/qr.png'). Pass a full relative path to override this.
Configure the defaults in config/qr-studio.php:
HasQrCode models also get saveQrCodeToDisk():
HasQrCode Trait
Add QR code generation directly to any Eloquent model. The trait is flexible: return a plain string for URL / text QR codes, or return an array and override qrCodeType() for structured data types (MeCard, vCard, WiFi, etc.).
URL / plain-text model
In Blade:
Structured data types
Return an array from qrCodeData() and override qrCodeType() to match the generator's data type method:
Supported qrCodeType() return values (must match a generator magic method):
| Value | Data type |
|---|---|
meCard |
MeCard (iOS/Android) |
vCard |
vCard 3.0 |
wifi |
WiFi network |
email |
Email with subject/body |
phoneNumber |
Phone number |
sMS |
SMS with body |
geo |
GPS coordinates |
bTC |
Bitcoin payment |
calendarEvent |
iCal event |
Trait API
| Method | Signature | Description |
|---|---|---|
qrCodeData() |
qrCodeData(): string\|array |
Must be implemented. Return a string for URL/text, or an array for structured types. Throws BadMethodCallException if not overridden. |
qrCodeType() |
qrCodeType(): string |
Override to set the data type when returning an array from qrCodeData(). Default: 'text'. |
qrCodeSvg() |
qrCodeSvg(int $size = 0): string |
Returns an inline SVG string. $size = 0 uses the package config default. |
qrCodeDataUri() |
qrCodeDataUri(int $size = 0, Format $format = Format::Png): string |
Returns a base64 data URI. Defaults to PNG. |
Combining Options
Options are fully composable via fluent chaining:
API Reference
Complete reference for all public methods on QrCodeGenerator (accessed via the QrCode facade).
generate()
Signature: generate(string $text, ?string $filename = null): HtmlString|string|null
Description: Generates the QR code for the given text. When $filename is provided the output is written to that path and null is returned. Without a filename, an HtmlString is returned (or a plain string outside of Laravel). Calls reset() automatically after execution, so all per-call options are cleared.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$text |
string |
Yes | The content to encode in the QR code |
$filename |
?string |
No | Absolute path to write the output file |
Exceptions: WriterException if the underlying BaconQrCode writer fails.
Example:
toDataUri()
Signature: toDataUri(string $text): string
Description: Generates the QR code and returns a base64-encoded data URI. Ideal for embedding in emails, PDFs, or any context where external URLs are blocked. Calls reset() automatically after execution.
- SVG format returns
data:image/svg+xml;base64,... - PNG format returns
data:image/png;base64,...
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$text |
string |
Yes | The content to encode |
Exceptions: WriterException if the underlying writer fails.
Example:
format()
Signature: format(Format|string $format): static
Description: Sets the output format. Accepts a Format enum (recommended) or the strings 'svg', 'eps', or 'png'.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$format |
Format\|string |
Yes | Output format: svg, eps, png |
Exceptions: InvalidArgumentException if a string other than svg, eps, or png is passed.
Example:
size()
Signature: size(int $pixels): static
Description: Sets the width and height of the generated QR code in pixels. Minimum value is 1.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$pixels |
int |
Yes | Size in pixels (minimum: 1) |
Exceptions: InvalidArgumentException if $pixels is less than 1.
Example:
margin()
Signature: margin(int $margin): static
Description: Sets the quiet zone (whitespace border) around the QR code. Minimum value is 0.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$margin |
int |
Yes | Quiet zone width in pixels (min 0) |
Exceptions: InvalidArgumentException if $margin is negative.
Example:
encoding()
Signature: encoding(string $encoding): static
Description: Sets the character encoding used when encoding the text. The value is converted to uppercase internally. Defaults to UTF-8.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$encoding |
string |
Yes | Character encoding (e.g. UTF-8) |
Example:
errorCorrection()
Signature: errorCorrection(ErrorCorrection|string $errorCorrection): static
Description: Sets the error correction level. Higher levels allow the code to be read even when partially obscured (e.g. with a logo). Accepts an ErrorCorrection enum or the strings 'L', 'M', 'Q', 'H'.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$errorCorrection |
ErrorCorrection\|string |
Yes | Error correction level: L, M, Q or H |
Exceptions: InvalidArgumentException if a string other than L, M, Q, or H is passed.
Example:
style()
Signature: style(Style|string $style, float $size = 0.5): static
Description: Sets the module (dot) rendering style. Accepts a Style enum or the strings 'square', 'dot', or 'round'. The $size parameter controls the fill ratio of each module and must be strictly between 0 and 1.
Important:
dotandroundstyles render all pixels as dots, including the three finder-pattern eyes. Without an expliciteye()call the finder squares disappear and scanners fail to orient the code. Always combinestyle('dot', ...)orstyle('round', ...)with->eye('square')or->eye('circle').
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$style |
Style\|string |
Yes | Module style: square, dot, or round |
$size |
float |
No | Fill ratio, must be > 0 and < 1. Default: 0.5 |
Exceptions: InvalidArgumentException if an invalid style string is passed, or if $size is >= 1 or <= 0.
Example:
eye()
Signature: eye(EyeStyle|string $style): static
Description: Sets the finder-eye (corner square) rendering style. Accepts an EyeStyle enum or the strings 'square', 'circle', or 'pointy'.
Required when using
style('dot')orstyle('round')to ensure the finder pattern remains recognizable to scanners.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$style |
EyeStyle\|string |
Yes | Eye style: square, circle, or pointy |
Exceptions: InvalidArgumentException if a string other than square, circle, or pointy is passed.
Example:
color()
Signature: color(int $red, int $green, int $blue, ?int $alpha = null): static
Description: Sets the foreground color of the QR code modules. Alpha channel is optional: 0 = fully opaque, 127 = fully transparent.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$red |
int |
Yes | Red channel (0–255) |
$green |
int |
Yes | Green channel (0–255) |
$blue |
int |
Yes | Blue channel (0–255) |
$alpha |
?int |
No | Alpha (0 = opaque, 127 = transparent) |
Example:
backgroundColor()
Signature: backgroundColor(int $red, int $green, int $blue, ?int $alpha = null): static
Description: Sets the background color of the QR code. Alpha channel follows the same convention as color(): 0 = fully opaque, 127 = fully transparent.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$red |
int |
Yes | Red channel (0–255) |
$green |
int |
Yes | Green channel (0–255) |
$blue |
int |
Yes | Blue channel (0–255) |
$alpha |
?int |
No | Alpha (0 = opaque, 127 = transparent) |
Example:
eyeColor()
Signature: eyeColor(int $eyeNumber, int $innerRed, int $innerGreen, int $innerBlue, int $outerRed = 0, int $outerGreen = 0, int $outerBlue = 0): static
Description: Sets the color of one of the three finder eyes independently. $eyeNumber is 0, 1, or 2. Each eye has an inner color (the center dot) and an outer color (the surrounding frame). When only inner colors are provided, outer defaults to black (0, 0, 0).
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$eyeNumber |
int |
Yes | Eye index: 0, 1, or 2 |
$innerRed |
int |
Yes | Inner dot red channel (0–255) |
$innerGreen |
int |
Yes | Inner dot green channel (0–255) |
$innerBlue |
int |
Yes | Inner dot blue channel (0–255) |
$outerRed |
int |
No | Outer frame red channel. Default: 0 |
$outerGreen |
int |
No | Outer frame green channel. Default: 0 |
$outerBlue |
int |
No | Outer frame blue channel. Default: 0 |
Exceptions: InvalidArgumentException if $eyeNumber is not 0, 1, or 2.
Example:
gradient()
Signature: gradient(int $startR, int $startG, int $startB, int $endR, int $endG, int $endB, GradientType|string $type): static
Description: Applies a gradient fill to the QR code foreground modules. The gradient runs from the start color to the end color according to the specified type. Only works with SVG format or PNG with ext-imagick installed. Passing a GradientType enum is recommended; strings are accepted for compatibility.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$startR |
int |
Yes | Start color red channel (0–255) |
$startG |
int |
Yes | Start color green channel (0–255) |
$startB |
int |
Yes | Start color blue channel (0–255) |
$endR |
int |
Yes | End color red channel (0–255) |
$endG |
int |
Yes | End color green channel (0–255) |
$endB |
int |
Yes | End color blue channel (0–255) |
$type |
GradientType\|string |
Yes | Gradient direction/shape (see Enum Reference below) |
Exceptions: InvalidArgumentException if an invalid gradient type string is passed. RuntimeException at render time if PNG format is used without ext-imagick.
Example:
theme()
Signature: theme(Theme|string $theme): static
Description: Applies a built-in visual preset to the QR code. The preset configures colors, gradient, module style, and eye style in a single call. Any method chained after theme() overrides the corresponding preset value.
Available themes: ocean, sunset, forest, midnight, coral (use the Theme enum or a plain string).
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$theme |
Theme\|string |
Yes | Theme name or Theme enum case |
Exceptions: InvalidArgumentException if an unrecognised theme name is passed.
Example:
saveToDisk()
Signature: saveToDisk(string $text, string $filename, ?string $disk = null): string
Description: Generates the QR code and persists it to a Laravel filesystem disk. Returns the storage path where the file was written. Calls reset() automatically after execution.
- When
$filenamecontains no/, the configuredpathfromconfig('qr-studio.path')is prepended automatically. - When
$diskisnull, the configureddiskfromconfig('qr-studio.disk')is used. - The file extension in
$filenamedetermines nothing — useformat()to control the output format.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$text |
string |
Yes | The content to encode in the QR code |
$filename |
string |
Yes | Storage path (e.g. 'user-42.png' or 'invoices/qr.svg') |
$disk |
?string |
No | Filesystem disk name. null = use config default |
Returns: string — the storage path where the file was saved.
Exceptions: WriterException if the QR writer fails. RuntimeException if the disk cannot write.
Example:
merge()
Signature: merge(string $filepath, float $percentage = 0.2, bool $absolute = false): static
Description: Overlays an image (e.g. a logo) centered over the QR code. Only applies when using PNG format — silently has no effect for SVG or EPS. $percentage is the fraction of the QR code's width that the image should occupy (0.0–1.0). When $absolute is false and $filepath does not start with /, the path is prepended with base_path(). Use errorCorrection('H') to ensure the code remains scannable after the overlay.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$filepath |
string |
Yes | Path to the image file |
$percentage |
float |
No | Logo size as fraction of QR width. Default: 0.2 |
$absolute |
bool |
No | If true, skip base_path() prepending. Default: false |
Exceptions: InvalidArgumentException if the file cannot be read.
Example:
mergeString()
Signature: mergeString(string $content, float $percentage = 0.2): static
Description: Same as merge() but accepts the raw binary content of the image directly instead of a file path. Useful when the image has already been loaded into memory (e.g. fetched via HTTP). Only applies when using PNG format.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
$content |
string |
Yes | Binary image content |
$percentage |
float |
No | Logo size as fraction of QR width. Default: 0.2 |
Example:
Limitations & Known Issues
1. Dot/Round style without eye() — code will not scan
DotsModule and RoundnessModule in BaconQrCode render every pixel as a dot, including the three finder-pattern eyes. Without those recognizable squares, scanners cannot determine the orientation of the code and will fail to read it, even though the QR data is valid.
Rule: always call ->eye('square') or ->eye('circle') whenever you use style('dot', ...) or style('round', ...).
2. PNG gradient without ext-imagick throws RuntimeException
Gradient rendering for PNG requires Imagick. When only GD is available (the fallback path), calling ->gradient() before generating a PNG throws a RuntimeException at render time — not at configuration time.
Solutions:
- Install
ext-imagickfor full PNG gradient support. - Use SVG format instead — gradients always work in SVG with no extra extension required.
3. merge() / mergeString() is PNG-only
Logo overlay is performed using bitmap compositing and silently has no effect when the output format is SVG or EPS. No error is thrown and no warning is emitted — the image just does not appear.
Always combine merge() with format('png') and errorCorrection('H') (H provides 30% redundancy, which compensates for the area covered by the logo).
4. Gradient without eyeColor() may produce low-contrast finder eyes
When eyeColor() is not set, finder eyes inherit the gradient fill. If the gradient produces a light color at the eye positions and the background is also light, the eye borders become invisible and scanners fail.
Solution: Use eyeColor() on all three eyes with high-contrast colors whenever using a gradient.
5. style() size must be strictly less than 1.0
The $size parameter in style('dot', $size) must be in the range (0, 1). Passing 1.0 or any value >= 1 throws an InvalidArgumentException immediately. Values close to 1.0 also produce nearly solid modules with no visible gap between them.
Recommended range: 0.5 to 0.7.
6. Low error correction with dot/round modules reduces scan reliability
Error correction levels L (7%) or M (15%) combined with dot or round modules often produce codes that real-world scanners refuse. The reduced per-module fill area leaves very little redundancy to compensate for noise, printing imperfections, or screen glare.
Always use errorCorrection('H') when using dot or round module styles.
7. EPS format has no browser preview
EPS (Encapsulated PostScript) is a valid vector format understood by print software (Illustrator, InDesign, macOS Preview), but browsers cannot render it inline. Using an EPS data URI in an <img> tag will display nothing.
EPS is intended for print pipelines. Use response()->qrcode('...', Format::Eps) to stream it from a route, or write it to a file with generate($text, $path). For web display, use SVG.
8. State resets automatically after generate() and toDataUri()
Every call to generate() or toDataUri() triggers an internal reset(), clearing all per-call options (format, size, style, colors, etc.) and returning the instance to config defaults. Do not split configuration across multiple statements expecting state to persist:
Enum Reference
All enums are backed enums so they work alongside their string equivalents.
Testing
Migrating from simplesoftwareio/simple-qrcode
This package was built as a modernized continuation of simple-qrcode. The core fluent API is identical, so most projects require only minor changes.
Installation
Facade
That's usually the only change needed. All existing method calls (generate, size, format, color, style, eye, gradient, merge, etc.) work identically.
What's new
| Feature | simple-qrcode | qr-studio |
|---|---|---|
| PHP 8.2+ strict types | — | ✓ |
| Backed enums for all options | — | ✓ |
toDataUri() |
— | ✓ |
| vCard 3.0 data type | — | ✓ |
| MeCard data type | — | ✓ |
| Calendar Event data type | — | ✓ |
@qrcode Blade directive |
— | ✓ |
response()->qrcode() macro |
— | ✓ |
Artisan qrcode:generate command |
— | ✓ |
| Publishable config file | — | ✓ |
HasQrCode Eloquent trait |
— | ✓ |
Automatic state reset after generate() |
— | ✓ |
EyeStyle::Pointy (BaconQrCode 3.x) |
— | ✓ |
PNG via ext-gd fallback (no Imagick needed) |
— | ✓ |
| WhatsApp data type | — | ✓ |
| Built-in visual themes (ocean, sunset, forest…) | — | ✓ |
saveToDisk() — persist to any filesystem disk |
— | ✓ |
| Laravel 11 / 12 / 13 support | ✓ | ✓ |
| SVG / EPS / PNG formats | ✓ | ✓ |
| Image merging (logo overlay) | ✓ | ✓ |
| Colors, gradients, eye colors | ✓ | ✓ |
| Email, Phone, SMS, Geo, WiFi, BTC | ✓ | ✓ |
Changelog
See CHANGELOG.md.
Contributing
See CONTRIBUTING.md.
Security
See SECURITY.md.
License
MIT — see LICENSE.
All versions of qr-studio with dependencies
ext-gd Version *
bacon/bacon-qr-code Version ^3.0
spatie/laravel-package-tools Version ^1.16
illuminate/contracts Version ^11.0|^12.0|^13.0