How to Improve WordPress Load Times Using Transients

WordPress Transients Tutorial
Standard

WordPress load times can be a serious concern if you’re working with a complicated page that has a lot of queries or API calls.

I’ve worked with several enterprise publishing sites, and site speed was always a concern because of the complex features that fill the page: related news, latest posts from several categories, news tickers, social media feeds, etc.

Loading so many features is a concern because hitting the database so many times so quickly can be a burden on the server, and when you factor in the limited number of API calls many services allow, we need a solution to store data for a brief period of time.

WordPress Transients

Enter WordPress transients.

Transients save information to the database for quick access. These are also nice because they can expire after a limited time, meaning that fresh data can be fetched based on time intervals.

The best part is they’re easy to use.

They work a lot like options or post meta in WordPress. It’s a simple function that takes a name, a value, and an optional expiration time.

Here’s how they work:

First, you check to see if anything is stored in the transient.

$value = get_transient( 'jr3_transient' );

If the desired data is not there, get your data and store it in the transient.

$value = jr3_get_data();
set_transient( 'jr3_transient', $value );

The nice thing is that you can set an expiration time for the transient. This means that if you need to only store the data temporarily, even if it’s just a few seconds, you can do that by adding the third parameter to the function.

// Store for 5 minutes.
set_transient( 'jr3_transient', $value, 5 * MINUTE_IN_SECONDS );

Here’s a more fully-featured example:

<?php
/**
* Get News posts.
*
* This is from a tutorial found here:
* @link https://johnregan3.wordpress.com/how-to-improve-wordpress-load-times-using-transients
*
* @since 1.0.0
* @uses jr3_news_query
*
* @return array Array of news posts, else an empty array.
*/
function jr3_get_news() {
$output = get_transient( 'jr3_news' );
/*
* Side note:
* When an empty array is possible
* (like if a stored array of posts is empty because
* none were found), don't do the typical "! empty()" check.
*
* If the transient is not found, it will return false.
*/
if ( ( false !== $output ) && ( is_array( $output ) ) ) {
// Return the array stored in the transient.
return $output;
}
// Imaginary function to fetch data.
$results = jr3_news_query();
if ( is_array( $results ) ) {
// Set our transient to expire in one hour.
set_transient( 'jr3_news', $results, HOUR_IN_SECONDS );
return $results;
}
// At a minimum, return an empty array.
return array();
}

Advanced Transient Names

It’s possible that you want to store the transient name based on the post being viewed, as may be the case if you are storing data for posts related to the present post. You can do this by adding the post ID to the transient name:

$transient_name = 'jr3_transient_' . get_the_ID();
$value = jr3_get_data();
set_transient( $transient_name, $value );

Super-Advanced Transient Names

It’s important to note that transient names are limited to 191 characters. This can be an issue when storing a specific WP_Query call. I run into this when I’m doing taxonomy queries, which are notoriously slow. In order to save this data in a transient name, I actually use the query arguments to generate the transient name.

Let’s say this is our query:

$wp_query_args = array(
'post_type' => 'book',
'tax_query' => array(
'relation' => 'OR',
array(
'taxonomy' => 'genre',
'fields' => 'slug',
'terms' => $genre_array,
),
array(
'taxonomy' => 'publisher',
'fields' => 'slug',
'terms' => $publisher_array,
),
),
);

Since we don’t know for sure what the $genre_array and $publisher_array will hold, we can’t hard-code a static transient name.

To solve this, we’ll use the actual $wp_query_args array to generate the transient name. We do this using two methods.

First, we turn the array into a string format using maybe_serialize(), but this still leaves us with the issue of running into the 191-character limit on the transient name.

Second, to handily convert this potentially long serialized string into a shorter string, we convert it into an MD5 hash, which turns our long string into a 32-character string, allowing us room to prefix it.

$transient_name = 'jr3_' . md5( maybe_serialize( $wp_query_args ) );

This allows us to do something like this, ensuring that this specific query will be stored in the transient:

<?php
/**
* Get Books posts.
*
* This is from a tutorial found here:
* @link https://johnregan3.wordpress.com/how-to-improve-wordpress-load-times-using-transients
*
* @since 1.0.0
*
* @param array $genre_array An array of genre slugs.
* @param array $publisher_array An array of publisher slugs.
*
* @return array Array of books, else an empty array.
*/
function jr3_get_books( $genre_array, $publisher_array ) {
/*
* For the sake of this tutorial, we'll assume
* $genre_array and $publisher_array are valid arrays.
*/
$wp_query_args = array(
'post_type' => 'book',
'tax_query' => array(
'relation' => 'OR',
array(
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => $genre_array,
),
array(
'taxonomy' => 'publisher',
'field' => 'slug',
'terms' => $publisher_array,
),
),
);
// Generate the transient name.
$transient_name = 'jr3_' . md5( maybe_serialize( $wp_query_args ) );
$books = get_transient( $transient_name );
if ( ( false === $books ) || ( ! is_array( $books ) ) ) {
$books = array();
// Run the Query.
$query = new WP_Query( $wp_query_args );
if ( is_array( $query->posts ) ) {
// Rename for output.
$books = $query->posts;
// Set our transient using our generated name.
set_transient( $transient_name, $books, HOUR_IN_SECONDS );
}
}
return $books;
}

Conclusion

If you are working on a site with lots of queries, you really should be using transients. They are extremely hand for temporarily storing data, whether it be an array of posts, or the results of an API call (like fetching recent tweets). They are easy-to-use, and can be set up in just a few minutes.

Further Reading

How To Add Custom Editor Styles to Gutenberg

Standard

Adding Custom Gutenberg editor styles in WordPress is a nice touch to any theme, as it allows authors to get a basic preview of their content before it gets published. It seems like a complicated task, but it’s actually pretty simple, once you get started.

Before

Default Gutenberg Editor Styles

After

Custom Gutenberg Editor Styles

The PHP

It begins with registering and enqueueing a CSS file in your theme.

<?php
/**
* Enqueue the Gutenberg editor stylesheet.
*
* Put this in your functions.php.
*
* @action enqueue_block_editor_assets
*/
function jr3_enqueue_gutenberg() {
// Make sure you link this to your actual file.
wp_register_style( 'jr3-gutenberg', get_stylesheet_directory_uri() . '/css/editor.css' );
wp_enqueue_style( 'jr3-gutenberg' );
// This font is enqueued for the demo only. You probably won't need this.
wp_register_style( 'jr3-webfonts', 'https://fonts.googleapis.com/css?family=Montserrat&#39; );
wp_enqueue_style( 'jr3-webfonts' );
}
add_action( 'enqueue_block_editor_assets', 'jr3_enqueue_gutenberg' );

The CSS

The CSS is a bit trickier because there are so many blocks and elements to cover. Here is an example that I’ve put together for this demo that can be a starting place for you.

/* Custom Editor Styles */
/*
* With some edits, this can be used as a base for your Custom Editor Styles.
* Note that this is for demonstration purposes only, and some elements may not
* be covered here.
*/
/* Approximate the theme width, except for full-width images. */
.wp-block:not( '.editor-block-list__block["data=full"]' ) {
width: 95%;
max-width: 1000px;
}
/* Fonts */
/* Note that Montserrat is enqueued in the PHP function that enqueues this file */
.editor-writing-flow .wp-block textarea,
.editor-writing-flow .wp-block .wp-block-freeform,
.editor-rich-text p,
.editor-post-title__input,
.wp-block-quote__citation {
font-family: 'Montserrat', Arial, Helvetica, sans-serif;
}
/* TinyMCE Editor */
.editor-styles-wrapper p,
.editor-rich-text p,
.editor-styles-wrapper blockquote {
font-size: 16px;
line-height: 22px !important;
}
.editor-writing-flow .wp-block a {
color: #00a2ad !important;
}
/* Headings */
.editor-writing-flow .wp-block h1,
.editor-writing-flow .wp-block h3,
.editor-writing-flow .wp-block h3{
font-weight: bold;
}
.editor-writing-flow .wp-block h1 {
font-size: 36px;
line-height: 1.5em;
}
.editor-writing-flow .wp-block h2 {
font-size: 25px;
line-height: 1.5em;
}
.editor-writing-flow .wp-block h3 {
font-size: 16px;
line-height: 1.5em;
}
/* The Post Title */
.editor-post-title__block .editor-post-title__input {
color: #00a2ad;
text-align: center;
}
/* Blockquote styles */
.wp-block blockquote {
font-style: italic;
color: #aaa;
margin-left: 20px;
border-left: 0;
padding-left: 0;
}
.wp-block blockquote .editor-rich-text {
padding-left: 3rem;
}
.wp-block blockquote:before {
color: #ccc;
content: '\201C' !important;
font-size: 4em;
position: absolute;
top: 10px;
}
.wp-block-quote:not(.is-large):not(.is-style-large) {
border-left: 0;
margin-left: 0;
padding-left: 0;
}

How to Add Full Width Images in Gutenberg

Theme Preview with a Full-Width Image
Standard

Full width images are a sweet new feature that Gutenberg offers to WordPress theme developers. In order to enable these in your theme, it takes just a few lines of code.

Problem #1

By default, the Gutenberg Image Block only has the three classic alignment options: left-aligned, centered, and right-aligned.

Gutenberg Default Image Alignment Options
Gutenberg Default Image Alignment Options

Enabling Wide Images in the Gutenberg Editor

First, a bit of PHP.  Add this to your theme’s functions.php, or wherever else you are adding your add_theme_support() functions.

<?php
/**
* Add Theme Support for wide and full-width images.
*
* Add this to your theme's functions.php, or wherever else
* you are adding your add_theme_support() functions.
*
* @action after_setup_theme
*/
function jr3_theme_setup() {
add_theme_support( 'align-wide' );
}
add_action( 'after_setup_theme', 'jr3_theme_setup' );

Now, you can find two new icons on your Image Gutenberg Block, wide-align, and full-width.

Gutenberg Image Block Updated Options

When one of these options is selected, it will display correctly in the editor.  If you select wide-align, the image gets wider, and if you select full-width, the image fills the editor horizontally.

Wide Image Previews in the Gutenberg Editor

Gutenberg Image Block Wide Width in the Editor
A wide image in the Gutenberg Editor
Gutenberg Image Block Full Width in the Editor
A full-width image in the Gutenberg Editor

Problem #2

There’s just one issue: Although WordPress adds special classes to the image markup, this doesn’t affect your actual theme styles.

Gutenberg Image in the Theme, unstyled
An unstyled full-width image in the Theme.

The Solution

To solve this, add your own CSS.  Here’s a snippet I came up with:

.alignwide {
/* Set these margins to work with your own theme. */
margin-left: -80px;
margin-right: -80px;
max-width: 100vw;
}
.alignfull {
margin-left: calc(-100vw / 2 + 100% / 2);
margin-right: calc(-100vw / 2 + 100% / 2);
max-width: 100vw;
}
.alignfull img {
width: 100vw;
}

A few notes about the CSS:

  • calc() tells the browser to calculate a value (usually) based on the screen size.
  • vw refers to “viewport width,” or screen width.

The Result

After the styles are applied:

Gutenberg Wide Image in the Theme
A wide-aligned image in the theme after adding the CSS.
A full-width image in the theme after adding the CSS.
A full-width image in the theme after adding the CSS.

So, with less than 20 lines of code, you can add this powerful and attractive feature to your themes.

Further Reading

OOP with WordPress – For the Total Newbie

Standard

Object-Oriented Programming (OOP) is a common method used to encapsulate code. Although it can be used for techniques much more advanced than we’ll discuss here, it can be used for basic plugins quite easily so you can learn its basics.

In this tutorial, we’ll create a short plugin that creates a Custom Post Type called “Books,” and an associated taxonomy called “Genres.” This is a fairly common operation in WordPress, and can certainly be created without using OOP, but since you’re probably already familiar with that process, it will serve as a good base for this tutorial.

Skip to the full code »

The primary “element” of OOP is the Class. For our purposes, it’s a wrapper that holds all of the internal functions, which in the context of OOP are called methods.

Creating a Simple Class

We start by creating our Class.

class JR3_Books {
     static function setup() {}
}
add_action( 'plugins_loaded', array( 'JR3_Books', 'setup' ) );

Our Class is “JR3_Books.” Each word in a Class’s name is capitalized, and underscores represent spaces.

Inside of it, we place a method that we’ll call setup(). You’ll note that you usually want to prefix your functions in WordPress to avoid conflicts, but since this is within our Class, it isn’t necessary.

You’ll note the word static before the method setup(). This is important for the way that we will be calling our methods in this tutorial, but the reason why isn’t important right now.

Firing the Class

Finally, we called the plugins_loaded action after the class. This is an important thing to note, as we’ll use a similar format within the Class.

Note that usually, an action looks like this:

add_action( 'plugins_loaded', 'setup' );

However, we have to let the add_action() know that setup() is located within our Class.

This is done by turning the second argument from a simple string into an array that includes the name of our Class, which gives us this:

add_action( 'plugins_loaded', array( 'JR3_Books', 'setup' ) );

Note: There are a lot of ways to instantiate a Class, and some are more appropriate than others. For the sake of simplicity and consistency in this tutorial, I’m taking the simple add_action() route

Adding A Method

Now, we add our method to register the post type. This will be done very similarly to how we commonly use register_post_type(), and we’ll use an action to fire this off in just a minute.

For now, this method goes within the Class, just like our setup() method.

static function register_books_cpt() {
     register_post_type( 'jr3_books', array(...) );
}

Note that I haven’t filled in the register_post_type() function completely here for the sake of clarity.

So, right now, our plugin doesn’t do anything. As I said above, we need to use an action to make this new method fire off. We do this by adding the appropriate action within our setup() method.

static function setup() {
     add_action( 'init', array( __CLASS__, 'register_books_cpt' ) );
}

Once again, you’ll note that we’re using an array as the second argument in the action. This time, however, we aren’t using the Class name, “JR3_Books.” Within a class, you use the Magic Constant __CLASS__. Also, the second value in the array is the name of our new method.

To translate this action into words, it tells the code to, on init, look inside of this Class for the method register_books_cpt.

In the code snippet below, you’ll see that I’ve also added a method for adding a custom Taxonomy (called, “Generes”), using the same technique.

Conclusion

What we’ve done here is we created a Class to hold our code. Inside of it, we added a setup() method to maintain the actions we’ll fire during our plugin. Then, to kick things off, we added the add_action( 'plugins_loaded' ... ) to tell WP to load our Class.

Naturally, this is a very high-level view of OOP. These can do extremely intricate and complex functions for you on your projects, and I hope that this will get you on your way to understanding how they work!

BONUS: The code below is a partial example of what we’ve covered. Here’s a fully-functional example this code that you can place in your wp-content/plugins directory to play around with.

Further Reading

 

Basic Example of this Tutorial

/*
* Plugin Header…
*
* Note: This particular block of code won't actually run because it doesn't have
* the details of the register_post_type and register_taxonomy functions filled in.
*/
class JR3_Books {
/**
* Fires all hooks for this plugin
*/
static function setup() {
add_action( 'init', array( __CLASS__, 'register_books_cpt' ) );
add_action( 'init', array( __CLASS__, 'register_genres_taxonomy' ) );
}
/**
* Basic setup of a Custom Post Type
* @see http://codex.wordpress.org/Function_Reference/register_post_type
*/
static function register_books_cpt() {
register_post_type( 'jr3_books', array(…) );
}
/**
* Register Custom Taxonomy for this Custom Post Type
* @see http://codex.wordpress.org/Function_Reference/register_taxonomy
*/
static function register_genres_taxonomy() {
register_taxonomy( 'jr3_genres', 'jr3_books', array(…) );
}
}
//Load the plugin by firing the setup() method.
add_action( 'plugins_loaded', array( 'JR3_Books', 'setup' ) );

view raw
oop-plugin-basic.php
hosted with ❤ by GitHub

Please Change Your Genesis Favicon

Standard

I love the Genesis framework* for WordPress. It is an amazing tool for speeding up the development process, and I even use it on my personal site.

Its wide acceptance across the WordPress world is unfortunately highlighted by the proliferation of Genesis favicons on these sites.

The Genesis Favicon is a black square or circle with a white capital “G” in it. It is a dead giveaway that you’re running your site on Genesis.

If you’re developing custom sites for your clients, you probably don’t want that visible. Your client would probably prefer to have their own branding in their favicon.

The fix for this is pretty simple, thanks to the hooks that Genesis offers.

What is a Favicon?

A favicon is that little square icon that appears in your browser window (or tab). It’s actually not a typical image, but an .ico file type.

The black circle in this browser tab is an example of a Genesis favicon.

The black circle in this browser tab is an example of a Genesis favicon.

To create your own favicon, create a square logo image with your brand of any size larger than 16x16px (you can even use transparent .pngs). Then, go to a site like favicon-generator.org and convert it to an .ico.

Including Your Custom Favicon in a Genesis Child Theme

Typically, this file is named “favicon.ico,” but you can call it whatever you want. The name “favicon.ico” is used in my code sample, so you may have to adjust that as needed.

Add your favicon to your Genesis Child theme’s directory, and add the following code to your child theme’s functions.php.

Note: Browsers are pretty stingy about caching these favicons. This means that you’ll need to open your site in a private/incognito window to see the changes take effect. New visitors to your site won’t need to do this.

<?php
/**
* Add custom Genesis favicon
*
* Dude, replace the default Genesis favicon so you don't look like a n00b.
* Create your custom favicon.ico and place it in your child theme's directory.
* Add this code to your child theme's functions.php
*
* Images can be converted to the .ico format here: http://www.favicon-generator.org/
*
* @author John Regan (john@johnregan3.com)
* @filter genesis_pre_load_favicon
* @uses get_stylesheet_directory_uri
* @param string Default Genesis favicon URL
* @return string Custom favicon URL
*/
add_filter( 'genesis_pre_load_favicon', 'my_custom_favicon' );
function my_custom_favicon( $favicon_url ) {
return get_stylesheet_directory() . '/favicon.ico';
}

*Not an affiliate link