Generate QR Codes in WordPress Posts

Learn how to use the off-the-shelf PHP QR Code library to generate QR Codes in your WordPress site. We’ll use the library to generate on-the-fly SVG QR codes – no PNG images or temporary files, just perfectly scalable QR Codes. We’ll also use the WordPress object cache to store our QR Codes short-term, so we don’t have to dynamically generate them for every page load. Nice and fast. We’ll wrap the whole thing up in a shortcode so it’s super easy to add QR Codes to any item of content.

Grab the PHP QR Code Source

“PHP QR Code” is an open source library written by Alexandre Assouad and hosted on GitHub. There are lots of files in the source tree, but we only need one of them.

  1. Navigate to https://github.com/t0k4rt/phpqrcode
  2. Click on phpqrcode.php
  3. In the top-right of the source code view, there’s a button that says “Raw”. Click the button – you should now see the raw PHP file in your browser.
  4. Save the file/page to your computer as “phpqrcode.php”. We’ll need it again in a moment.

Deploy some Scaffold Code

In your custom child theme, create an empty file called wpt-qrcode.php and a folder called wpt-qrcode. In the wpt-qrcode folder, create an empty file called wpt-qrcode.css. Next, take phpqrcode.php and copy it into the wpt-qrcode folder. This is what you should end up with in your custom child theme:

  • functions.php
  • style.css
  • wpt-qrcode
    • phpqrcode.php
    • wpt-qrcode.css
  • wpt-qrcode.php

To get started with some scaffold code (placeholder code), copy and paste the following into wpt-qrcode.php:

<?php

/**
 * WP Tutorials QR Codes
 *
 * https://wp-tutorials.tech/add-functionality/generate-qr-codes-in-wordpress-posts/
 *
 */

if (!defined('WPINC')) {
	exit('Do NOT access this file directly.');
}

Next, open functions.php and paste the following into it:

/**
 * WP Tutorials QR Codes.
 */
require_once 'wpt-qrcode.php';

Reload your site to make sure we didn’t break anything.

Now we can start adding the proper code… to do the actual work.

The Main PHP Bit

Our main chunk of PHP code only needs to do a a few things:

  1. Register the shortcode
  2. Enqueue a CSS file for the frontend.
  3. Call a function from inside phpqrcode.php.

…basically, it just joins everything together.

Start by opening wpt-qrcode.php, paste the following into it and save it.

<?php

/**
 * WP Tutorials QR Codes
 *
 * https://wp-tutorials.tech/add-functionality/generate-qr-codes-in-wordpress-posts/
 *
 * Registers a shortcode called "wpt_qrcode"
 *
 */

if (!defined('WPINC')) {
	exit('Do NOT access this file directly.');
}

const WPTQRC_IS_DIAGNOSTICS_ENABLED = false; //true;
const WPTQRC_IS_CACHING_ENABLED = true;
const WPTQRC_CACHE_DURATION = WEEK_IN_SECONDS;
const WPTQRC_MAX_CACHE_KEY_LENGTH = 45;

/**
 * Enqueue the frontend assets, if they've not already been euqueued.
 */
function wptqrc_include_hphqrcode_lib() {
	global $wptqrc_have_assets_been_loaded;

	if (is_null($wptqrc_have_assets_been_loaded)) {
		$base_dir = trailingslashit(dirname(__FILE__) . '/wpt-qrcode');

		// Include the PHP QR Code library... but only if it's not already been
		// included by another plugin.
		// Source: https://github.com/t0k4rt/phpqrcode
		if (!class_exists('QRcode')) {
			require_once $base_dir . 'phpqrcode.php';
		}

		$base_url = get_stylesheet_directory_uri() . '/' . pathinfo(__FILE__, PATHINFO_FILENAME) . '/';
		$version = wp_get_theme()->get('Version');

		wp_enqueue_style('wptqrc', $base_url . 'wpt-qrcode.css', '', $version);

		$wptqrc_have_assets_been_loaded = true;
	}
}

/**
 * Render the QR code as an HTML string.
 */
function wptqrc_do_shortcode_wpt_qrcode($atts) {
	$html = '';

	if (is_admin()) {
		// Don't do anything.
	} elseif (wp_doing_ajax()) {
		// Don't do anything.
	} else {
		// Enqueue our frontend assets.
		wptqrc_include_hphqrcode_lib();

		$args = shortcode_atts(
			array(
				'text' => '',
				'class' => '',
			),
			$atts
		);

		$is_from_cache = false;
		$diagnostics = array();
		$text = $args['text'];

		if (empty($text)) {
			error_log('QR Code: text cannot be empty.');
		} else {
			// Do we have any additional CSS classes to add to the
			// outer <div> ?
			$classes = array('wpt-qrcode');
			if (!empty($args['class'])) {
				$classes[] = $args['class'];
			}

			// If caching is enabled, look for this QRCode in the cache
			// from a previous run.
			$cache_key = 'qrcode_' . sanitize_title($text);
			if (strlen($cache_key) > WPTQRC_MAX_CACHE_KEY_LENGTH) {
				$cache_key = substr($cache_key, 0 - WPTQRC_MAX_CACHE_KEY_LENGTH);
			}
			$diagnostics[] = 'Cache key: ' . $cache_key;

			if (WPTQRC_IS_CACHING_ENABLED && !empty($qrcode_svg = wp_cache_get($cache_key))) {
				// We found an SVG QR Code for this text in the cache.
				$is_from_cache = true;
				$diagnostics[] = 'Code is from the cache';
			} else {
				// We have an '@' here to surpress an error message because
				// QRcode::svg() calls the PHP header() function, even though
				// WordPress has already sent headers. It's safe to ignore
				// the error.
				// NOTE: Alternatively, you could edit phpqrcode.php and remove
				// the call to header().
				ob_start();
				@QRcode::svg($text);
				$qrcode_svg = ob_get_clean();

				// The $qrcode_svg string contains an opening DOCTYPE that we
				// need to strip out, so find where our svg tag starts and
				// grab everything from that point onwards.
				$index_of_svg_tag = intval(strpos($qrcode_svg, '<svg '));
				if ($index_of_svg_tag > 0) {
					$qrcode_svg = substr($qrcode_svg, $index_of_svg_tag);
				}

				$diagnostics[] = 'Generated a new code';
			}

			// Build the HTML output.
			$html .= sprintf('<div class="%s">', esc_attr(implode(' ', $classes)));
			$html .= $qrcode_svg;
			$html .= '</div>';

			// If diagnostics are enabled, write some useful info to help
			// with testing.
			if (WPTQRC_IS_DIAGNOSTICS_ENABLED) {
				foreach ($diagnostics as $diagnostic) {
					$html .= sprintf(
						'<div class="diagnostic">%s</div>',
						wp_kses($diagnostic, 'post')
					);
				}
			}

			// If caching is enabled, and we've just generated a new QRCode
			// SVG, save it to the cache it now... ready for next time.
			if (WPTQRC_IS_CACHING_ENABLED && !empty($qrcode_svg) && !$is_from_cache) {
				wp_cache_set($cache_key, $qrcode_svg, '', WPTQRC_CACHE_DURATION);
			}
		}
	}

	return $html;
}
add_shortcode('wpt_qrcode', 'wptqrc_do_shortcode_wpt_qrcode');

Now you should be able to edit some content on your site and add a shortcode, with parameters like text=”hello world” and class=”right”.

The main lump of code that renders the shortcode (HTML) should be easy to read. and you can control the key functions with WPTQRC_IS_DIAGNOSTICS_ENABLED and WPTQRC_IS_CACHING_ENABLED at the top of the file.

WordPress QR Shortcode
The WordPress QR shortcode

WordPress Object Caching

Caching here is a cool way to speed things up for the user. You can store stuff in the WordPress cache as key/value pairs. You just need a key (string) that’s unique to the object/value/variable/thing that you want to save in the cache.

The Key: For our QR Codes, we take the text for the QR Code and run it through the WordPress sanitize_title() function. This turns our QR Code text into a slug – getting rid of non-alpha-numeric characters.

The Value: All that phpqrcode really does is generate a long string with an <svg> element in it. Strings are really easy to store in an object cache.

On a fast WordPress server like this one, caching doesn’t make a noticeable difference. But if you’re using slow web servers, or if your website sees a lot of visitor traffic, then caching will make a big difference.

CSS Styles

To tidy things up a bit, open the file wpt-qrcode.css and paste the following into it. It’s easy to pick it apart and make it do what you need.

/**
 *  * WP Tutoruals : QR Code
 */

.wpt-qrcode,
.wpt-qrcode~.diagnostic {
    text-align: center;
}

.wpt-qrcode.left,
.wpt-qrcode.left~.diagnostic {
    text-align: left;
}

.wpt-qrcode.right,
.wpt-qrcode.right~.diagnostic {
    text-align: right;
}

.wpt-qrcode~.diagnostic {
    font-size: 10pt;
    background-color: #ffffff88;
    color: black;
    padding: 0.5em 0;
    margin-top: 0.5em
}

.wpt-qrcode > svg {
    width: 100%;
    height: auto;
    box-shadow: 0 0 1.5em #00000022;
}

Wrapping Up

That’s about all there is to it. Have fun sprinkling QR Codes around your WordPress projects.

If you come up with some interesting uses for this tutorial, let us know in the comments below 😎

Leave a Comment

Your email address will not be published. Required fields are marked *