How to Create a QR Code in PHP

September 28, 2021
Written by
Reviewed by

How to Create a QR Code in PHP

QR codes are almost everywhere these days!

It makes sense. They're small, readable on any modern smartphone without special software, and let us do so many things easily and quickly, such as checking in at a cafe, gaining access to a WiFi network, accessing a scooter on a summer vacation, and making a purchase.

Here are some examples that I found from around the web.

Some examples of QR codes.

So if you want to know how to create them in your PHP-based application, read on.

Prerequisites

To follow this tutorial, you need the following:

  • Previous experience with writing PHP code.
  • PHP 7.4 with the GD extension installed.
  • Composer installed globally.
  • A smartphone.

Let's create a QR code in PHP

First, we need to create a project directory structure to store all the files that we'll make use of. To do so, switch into the top-level directory, and run the commands below.

mkdir -p php-qr-code-generator \
    php-qr-code-generator/src/QR/{Image,Options} \
    php-qr-code-generator/public/img

cd php-qr-code-generator

If you're using Microsoft Windows, run the commands below. instead

mkdir php-qr-code-generator
mkdir php-qr-code-generator/src/QR/Image
mkdir php-qr-code-generator/src/QR/Options
mkdir php-qr-code-generator/public/img

cd php-qr-code-generator

Install dependencies

Next, it's time to install the project's sole dependency, chillerlan/php-qrcode. To do that, run the command below:

composer require chillerlan/php-qrcode

Write the code

Now, it's time to write some code. Using your IDE or text editor, create a new file named index.php in public, and add the code below to it.

<?php

declare(strict_types=1);

use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;

require_once('./../vendor/autoload.php');

$options = new QROptions(
  [
    'eccLevel' => QRCode::ECC_L,
    'outputType' => QRCode::OUTPUT_MARKUP_SVG,
    'version' => 5,
  ]
);

$qrcode = (new QRCode($options))->render('https://twilio.com');
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
  <title>Create QR Codes in PHP</title>
  <link rel="stylesheet" href="/css/styles.min.css">
</head>
<body>
<h1>Creating QR Codes in PHP</h1>
<div class="container">
  <img src='<?= $qrcode ?>' alt='QR Code' width='800' height='800'>
</div>
</body>
</html>

The code starts off by importing the required classes and including Composer's autoloader. After that, it initializes a new QROptions instance, named $options, which stores the options for generating the QR code.

This object is then used to initialize a QRCode object, which is responsible for generating the QR code, via its render() method. To render(), we pass the data to be stored in the QR code, which is Twilio's URL. Feel free to change it to whatever string you like.

After that, the QR code is rendered in the img tag of a small HTML page. The page includes a bit of extra markup to give it a more professional finish, using a custom stylesheet built with Tailwind CSS.

 

Make sure that you download styles.min.css to public/css, otherwise the page won't render as expected.

Test that the code works

With the code written, we need to test that it works. To do that, start your local server by running the following command from the project's root directory, using the public directory as the directory root.

php -S 0.0.0.0:8080 -t public

Then open http://localhost:8080 in your web browser. You'll see the page rendered similar to the image below.

The QR code rendered in the browser.

 

If you want to reduce the space, or quiet zone between the QR code and the border, try setting LogoOptions['quietzoneSize'] to a value from 1 - 3, or set LogoOptions['addQuietzone'] to false.

It’s also possible to add branding or logos to QR codes, such as for marketing purposes and for building user trust. To do that, we're going to make use of an example class that comes with chillerlan/php-qrcode: QRImageWithLogo.

First, copy vendor/chillerlan/php-qrcode/examples/QRImageWithLogo.php to src/QR/Image, and update its namespace to be App\QR\Image.

Then, using your IDE or text editor, create a new file named LogoOptions.php in src/QR/Options. In it, add the code below.

<?php

declare(strict_types=1);

namespace App\QR\Options;

use chillerlan\QRCode\QROptions;

class LogoOptions extends QROptions
{
  protected int $logoSpaceWidth;
  protected int $logoSpaceHeight;
}

This code extends the base QROptions class, allowing it to set a width and height around the image which is overlaid on the QR code.

Configure Composer's autoloader configuration

Next, as we've created some custom classes, we need to register a PSR-4 autoloader so that they'll be found at runtime. To do that, add the following JSON snippet to composer.json, after the require block.

"autoload": {
  "psr-4": {
    "App\\": "src/"
  }
}

Then, in your terminal in the root directory of the project, run the following command:

composer dump-autoload

Update the code

The next thing you need to do is to replace the definition of $options and $qrcode in public/index.php with the following code.

$options = new LogoOptions(
  [
    'eccLevel' => QRCode::ECC_H,
    'imageBase64' => true,
    'logoSpaceHeight' => 17,
    'logoSpaceWidth' => 17,
    'scale' => 20,
    'version' => 7,
  ]
);

$qrOutputInterface = new QRImageWithLogo(
  $options,
  (new QRCode($options))->getMatrix(''https://twilio.com'')
);

$qrcode = $qrOutputInterface->dump(
  null,
  __DIR__.'/../public/img/logo-twilio-mark-red.png'
);

NOTE: Make sure you add the import statements below

use App\QR\Image\QRImageWithLogo;
use App\QR\Options\LogoOptions;

The code starts off by initializing $options as a new LogoOptions instance. LogoOptions is a custom Options class that contains two additional member variables: $logoSpaceWidth, and $logoSpaceHeight. These influence the size of the image that is overlaid over the QR code.

$logoSpaceWidth and $logoSpaceHeight are not evenly divisible.

In addition to these two, this code sets two others:

  • imageBase64: This determines if the QR code will be rendered as binary data or a Base64-encoded string. I've set it to true, as it makes rendering the QR code simpler.
  • scale: This sets the size of a QR code pixel. The higher the value, the higher the QR code's quality.

We've also set eccLevel to ECC_H to allow us to overlay a logo on the QR code, and set version to 7 to allow for a higher level of error correction, required because of the increased level of data in the QR code.

After that, we initialize $qrOutputInterface as a new QRImageWithLogo instance, which handles generating a QR code and overlaying the specified image on it using PHP's GD extension.

$options and a new QRMatrix object are passed to QRImageWithLogo's constructor, so that it knows how to generate the QR code and the data to store in it.

The code finishes up by calling $qrOutputInterface's dump method to overlay the image over the QR code and return a Base64-encoded string representation of the QR code.

We passed null as the first parameter to dump. If we wanted to, we could generate a PNG file by specifying an absolute or relative path for the output file.

Add an image file

The last thing we need to do before testing the changes is to choose the image that we're going to overlay on the QR code. For the purposes of this article, I'm using Twilio's logo. To download it, first open it in Twilio's Library, then click the "Actual size_PNG" link on the lower right-hand side of the page.

If you choose to use a different image, make sure that you save the image in public/img and pass the image's path as the second argument to $qrOutputInterface->dump().

Test that the changes work

With the code and image in place, let's generate the new version of the QR code and see what it looks like. To do that, reload http://localhost:8080 in your browser, and you should see it rendered similarly to the screenshot below.

The QR code with branding rendered in the browser.

 

NOTE: If you want to change the QR code's matrix, experiment with setting maskPattern to either a value from 1 to 7, or QRCode::MASK_PATTERN_AUTO when initializing LogoOptions. It's quite interesting seeing the differences in how the QR code renders.

That's how you create QR codes in PHP

Packages like chillerlan/php-qrcode or one of the others available on Packagist can help you generate QR codes, with or without branding, in your applications. I highly recommend using them in your applications, as and where they make sense.

Are you considering using QR codes in your application after reading this tutorial? If so, if so I'd love to see what you build.

Matthew Setter is a PHP Editor in the Twilio Voices team and a polyglot developer. He’s also the author of Docker Essentials and Mezzio Essentials. When he’s not writing PHP code, he’s editing great PHP articles here at Twilio. You can find him at msetter@twilio.com; he's also settermjd on Twitter and GitHub.

Image credits: