DEV Community

Cover image for How to Implement QR Code Generation in Laravel
Nasrul Hazim Bin Mohamad
Nasrul Hazim Bin Mohamad

Posted on

How to Implement QR Code Generation in Laravel

QR codes are a practical tool for sharing data, and implementing them in a Laravel application can be straightforward and scalable. This blog post will guide you through building a QR code generation system using contracts, traits, and action classes.

Before we dive into the code, let's install the necessary packages and dependencies.

Step 1: Install SimpleSoftwareIO QR Code Package

To generate QR codes in Laravel, we will use the SimpleSoftwareIO QR Code package. It provides an easy-to-use API for creating QR codes in various formats, such as PNG, SVG, and more.

Run the following command to install the package:

composer require simplesoftwareio/simple-qrcode
Enter fullscreen mode Exit fullscreen mode

After installation, you’ll be able to use the QrCode facade to generate QR codes within your application.

Step 2: Install Imagick for PNG Format

If you are generating QR codes in PNG format (as we are in this example), it's recommended to install the Imagick extension. Imagick provides support for image processing, and the SimpleSoftwareIO QR Code package relies on it for creating and manipulating PNG files.

To install Imagick on your system, follow these steps:

For Ubuntu:

sudo apt-get install php-imagick
Enter fullscreen mode Exit fullscreen mode

For macOS (using Homebrew):

brew install imagemagick
brew install php@8.3-imagick # or php@your-version-imagick
Enter fullscreen mode Exit fullscreen mode

After installation, ensure that the imagick extension is enabled in your php.ini file.

For PHP environments, you may need to restart the server to reflect the changes:

php artisan serve
Enter fullscreen mode Exit fullscreen mode

Now that the package and Imagick are set up, let’s proceed with the implementation.


Step 3: Define the QR Code Contract

We start by defining a contract (interface) that enforces the methods required for generating a QR code. This contract ensures that any model implementing it will have the necessary functionality for handling QR code generation.

namespace App\Contracts;

interface QrCode
{
    public function generateQrCode(): self;

    public function getQrCodeColumnName(): string;

    public function getQrCodeIdentifier(): string;

    public function getQrCodeFormat(): string;

    public function getQrCodeSize(): string;

    public function getQrCodeLogo(): string;

    public function getQrCodePath(): string;

    public function getQrCodeContent(): string;
}
Enter fullscreen mode Exit fullscreen mode

This interface defines all the methods related to QR code creation, from specifying the QR code’s format and size to providing the content and file path.


Step 4: Implement the Trait for QR Code Interaction

Now, we create a trait to implement the logic that interacts with the QR code generation action class.

namespace App\Concerns;

use App\Actions\Qr\GenerateQrCode;
use App\Contracts\QrCode;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;

trait InteractsWithQrCode
{
    public static function bootInteractsWithQrCode()
    {
        static::creating(function (Model $model) {
            if ($model instanceof QrCode) {
                $model->generateQrCode();
            }
        });
    }

    public function generateQrCode(bool $force = false): self
    {
        $generator = new GenerateQrCode(
            $this->getQrCodeContent(),
            $this->getQrCodePath(),
            $this->getQrCodeFormat(),
            $this->getQrCodeSize(),
            $this->getQrCodeLogo(),
            $force
        );
        $generator->execute();

        if ($this instanceof HasMedia) {
            $this->copyMedia($this->getQrCodePath())->toMediaCollection('qr-code');
        }

        return $this;
    }

    public function getQrCodeColumnName(): string
    {
        return isset($this->qr_code) ? $this->qr_code : 'qr_code';
    }

    public function getQrCodeIdentifier(): string
    {
        return isset($this->qr_code_identifier) ? $this->qr_code_identifier : 'uuid';
    }

    public function getQrCodeFormat(): string
    {
        return isset($this->qr_code_format) ? $this->qr_code_format : 'png';
    }

    public function getQrCodeSize(): string
    {
        return isset($this->qr_code_size) ? $this->qr_code_size : '256';
    }

    public function getQrCodeLogo(): string
    {
        return file_exists(public_path('assets/logo.png')) ? public_path('assets/logo.png') : '';
    }

    public function getQrCodePath(): string
    {
        return storage_path(
            '/data/qr-codes/'.
            $this->{$this->getQrCodeIdentifier()}.
            '.'.
            $this->getQrCodeFormat()
        );
    }

    public function getQrCodeContent(): string
    {
        return data_get($this, $this->getQrCodeColumnName(), '');
    }
}
Enter fullscreen mode Exit fullscreen mode

This trait handles the QR code generation process, calling the GenerateQrCode action and storing the generated code.


Step 5: Create the Action Class to Generate QR Codes

We encapsulate the QR code generation logic into an action class. This class generates and saves the QR code to the specified path.

namespace App\Actions\Qr;

use CleaniqueCoders\LaravelContract\Contracts\Execute;
use SimpleSoftwareIO\QrCode\Facades\QrCode;

class GenerateQrCode implements Execute
{
    public function __construct(
        protected string $content,
        protected string $path,
        protected string $format = 'png',
        protected string $size = '256',
        protected string $logo = '',
        protected bool $force = false) {}

    public function execute()
    {
        try {
            $path = $this->path;

            $content = $this->content;

            if (file_exists($path) && ! $this->force) {
                return;
            }

            if ($this->force && file_exists($path)) {
                unlink($path);
            }

            $qrCode = QrCode::format($this->format)
                ->size($this->size)
                ->eye('square')
                ->margin(5)
                ->style('dot', 0.9);

            if ($this->logo) {
                $qrCode->merge($this->logo, .25, true);
            }

            file_put_contents(
                $this->path, $qrCode->generate($content)
            );
        } catch (\Throwable $th) {
            throw $th;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

This action class uses the SimpleSoftwareIO QrCode facade to generate a QR code with the specified format, size, and content. It also allows you to optionally include a logo and overwrite existing QR codes.


Step 6: Use the Contract and Trait in a Model

Lastly, integrate the QrCode contract and InteractsWithQrCode trait in a model that requires QR code generation, such as an Asset model.

namespace App\Models;

use App\Concerns\InteractsWithQrCode;
use App\Contracts\QrCode;
use App\Models\Base as Model;

class Asset extends Model implements QrCode
{
    use InteractsWithQrCode;

    public function getQrCodeContent(): string
    {
        return route('assets.qr', $this->{$this->getRouteKeyName()});
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the Asset model generates a QR code containing a URL to access the asset, and the QR code is created when a new asset is created.


Conclusion

By combining contracts, traits, and action classes, this implementation provides a scalable and maintainable solution for QR code generation in Laravel. With the help of the SimpleSoftwareIO QR Code package and Imagick for image handling, you can easily customize and extend this setup for any QR code generation needs.

Don't forget to install the necessary dependencies and ensure that the Imagick extension is enabled for PNG format support. Happy coding!

Top comments (0)