Getting Started with Service Workers

Getting started with Service Workers was both an exciting and extremely frustrating experience. It started when I was working on an old html5/canvas game that I had made as a proof of concept that used the AppCache API. I knew AppCache was on its way out and that Service Workers, along with the new Cache API, was the new fancy replacement and just hadn’t gotten around to implementing them. While working on the game I noticed a deprecation message about the AppCache API in the developer tools console, and this kicked off my journey into Service Workers.

As with learning any new API, I first started reading official documentation from Google Web Developers and Mozilla Developers Network, and then followed that up with some blogs and articles. In case others are still learning Service Workers here are links to each resource I used:

Once I got my mind wrapped around how all of these new APIs are intended to function, and work together, most of what I read seemed pretty straight forward and easy enough to implement. The final version of what I implemented was heavily influenced by the two articles (linked above) from RedFin Engineering. Those were the only articles that fully discussed a proper way to handle activating an updated service worker in spite of multiple browser tabs of the app being open. That said, though my experience was mostly positive there were two exceptions of which I wanted to share.

  1. My service-worker.js file absolutely refused to update (install and then activate). While debugging, the only workaround to this was to use browser developer tools to unregister the service worker and then refresh the page. It took several days of troubleshooting and scouring the internet for possible solutions, and even double checking my web server configuration to make sure expire headers were set properly. The most odd thing about this problem was that though my service-worker.js file wouldn’t update I was able to update any of the files being cached by the service worker with just a simple refresh of the page, including images, js, or css files. At the time I had my service worker script saved in my /js/ directory (/js/service-worker.js), and my solution to this problem was simply to move it to the app root (/sw.js) and everything magically began working. This made absolutely no logical sense to me so if anyone has any insight into why this fixed the problem I’d love to hear from you.
  2. The CacheStorage appeared to not be updating. Using Firefox Developer Edition version 83.0b5 I could see that my service worker was updating, and all old caches were deleted (according to console logs), but when I looked in the developer tools CacheStorage the version number was never correct. It was always the previous version still. In testing the same code in Google Chrome it all worked perfectly. I eventually came to find out that the CacheStorage was in fact updating (deleting all old caches), but it wasn’t reflected in the developer tools window until I closed them and re-opened them.

All in all, it was a wonderful learning experience and I’m better off for it, but wanted to share the struggles I encountered in case someone else is running into the same problems.


WordPress Plugin Conflicts and Compatibility

One of the reasons WordPress is so successful, and used so widely, is because it can do almost anything you need, particularly through the use of Plugins. Plugins add new features to a website by extending the core functionality of WordPress. However, not all plugins are created equally, and it’s impossible for even the best plugin authors to predict and account for all possible conflicts a plugin may have with other plugins.

The Problem

Where I work, we use User Role Editor Pro, WordPress MU Domain Mapping, and Redis Cache plugins on WordPress Multisite. We recently realized we were having some odd behavior and eventually determined it was a conflict between the three of these different plugins. Each of the conflicts we were experiencing revolved around features of the User Role Editor Pro plugin not working properly. I was about to contact the plugin author for support, but I tested the plugin on a clean WordPress Multisite and found that none of the problems existed. So, I knew the problem was either caused by our Must-Use Plugins or regular Plugins that we have installed.

WordPress MU Domain Mapping

The conflict we had with WordPress MU Domain Mapping was showing up on individual blogs (sites) when going to the User Role Editor admin page. Attempting to change any capability for a given role would not save. This was because the form action was incorrect (didn’t match the hostname in the address bar) and when the form was submit it would immediately redirect (302) but not pass any of the form POST data and was thus the equivalent of refreshing the page. This was caused by User Role Editor Pro loading before WordPress MU Domain Mapping, and when User Role Editor Pro loads it immediately defines a few constants (in the user-role-editor-pro/includes/define-constants.php file), specifically this line here:

define( 'URE_WP_ADMIN_URL', admin_url() );

The problem with this is that the WordPress MU Domain Mapping plugin filters the admin_url to change it to be the desired domain (which may differ from the original domain), but it hasn’t been loaded yet so it’s unable to do so. Worse yet is that this is a defined constant so it cannot be changed.

There were three possible solutions that came to mind: modify the User Role Editor Pro plugin to not load the define-constants.php file until all plugins have loaded, contact the plugin author to request that they modify their plugin to do so, or force the WordPress MU Domain Mapping plugin to load before the User Role Editor Pro plugin. It made the most sense to go with the third option because it would resolve potential conflicts of this nature with any of the other plugins that we use and it didn’t involve modifying a plugin.

In order to force the WordPress MU Domain Mapping plugin to load first it was simply a matter of manually loading it using one of our Must-Use Plugins. This is a very advanced, and infrastructure-specific, thing to be doing so I’m not sharing the code for that, but I basically ran the same code that’s in WordPress core settings.php file (where plugins are regularly loaded). However, this did fix the problem and we were able to change capabilities in the User Role Editor settings page, on individual blogs/sites.

Redis Cache

The conflict we were having with the Redis Cache plugin was showing up when attempting to “Update Network” in the User Role Editor Pro network admin settings page. What would happen is that the user role capabilities would be updated in the network admin page and on the main site in the multisite network, but the capabilities wouldn’t update on any of the other sites in the network. What tipped me off to the problem was when I looked at the raw database value in an individual sites options table and realized that the capabilities I was modifying were in fact actually set, but weren’t taking effect.

This was the result of Redis Cache not updating the database cache accordingly for each site in the network to reflect the changed user role capabilities. To test this theory it was easy to make a change to user role capabilities, “Update Network”, and then flush the cache in Redis Cache settings and then check if the capabilities were correct on individual sites in the network, which they were.

Knowing the solution was as simple as flushing the cache was easy enough to do, however even with good documentation this procedure was likely to be forgotten several months in the future, or if another admin needed to change user role capabilities. So, I took it one step further and added to one of our Must-Use Plugins some code to automatically flush the redis cache when the User Role Editor Pro plugin updates the network with new user role capabilities.

function my_ure_direct_network_roles_update() {
global $wp_object_cache;

// Check if the redis_status method exists (Redis Cache is installed and active)
// Check if redis_status returns true, which means that Redis Cache has a connection
if (method_exists($wp_object_cache, 'redis_status') && $wp_object_cache->redis_status()) {
add_action('ure_direct_network_roles_update', 'my_ure_direct_network_roles_update');

This was a simple solution that automated the process and guaranteed less frustration in the future.

At the end of the day, having these wonderful plugins has saved way more time that I’ve spent in troubleshooting, but it serves as a great example of how plugins can conflict with each other.

Developing for Gutenberg vs Beaver Builder

I want to start by saying that I didn’t want to do a Gutenberg vs Beaver Builder comparison, since in their current state I don’t see them as direct competitors. However developing for both tools is different enough I decided to write a comparison between developing for Gutenberg vs Beaver Builder, and why my preference is Beaver Builder.

Despite my preference of developing for Beaver Builder I think Gutenberg is a dramatic improvement over the classic editor and will be the foundation of a new era for WordPress, and you can read more about that in my WordPress Gutenberg Review.

My Development Environment

I’d like to give an overview of my two primary development environments as this is part of the basis for my preferences.

  • Personal Development Environment
    • I regularly work on a Mac OS X computer and Windows 10 computer. I use OneDrive to share all of my files between the two computers. Each are setup with Node, PHP, Phing, Git, etc. I develop directly on my dev web server (ssh-on-save) and then build and deploy where necessary. This allows me to move from one computer to another with no interruption, and no need to maintain a XAMP stack on each local computer.
  • Work Development Environment
    • My work environment is very similar, except that I’m working exclusively on a Windows 10 computer and all files are saved on a local network drive so that they can be shared with co-workers. We’re utilizing a dev/stage/prod server setup there as well (with ssh-on-save to dev).

Programming Languages

I also want to make it clear that I love both PHP and JavaScript and enjoy working with them both on a daily basis. The one caveat is that I question if JavaScript development is heading in the right direction. The features being added to JavaScript (at a rapid pace) are fantastic, but with the advent of NPM, and the desire to use modern features (not always supported by browsers yet), a need for build tools has become the norm and dramatically increased project complexity. For several years there was a growing sense across the web development community that jQuery was gross and added bloat to a site and that clean vanilla JS was superior (I don’t necessarily disagree), yet today we seem to have no problem including Bootstrap, React, Redux, among whatever other dependencies we need. This doesn’t even touch on the 1,500+ files used to create a “Hello World” React app (using create-react-app). All of that is to say that I question the wisdom of following suit with the WordPress editor, and my skepticism certainly affects my preferences between developing for Gutenberg vs Beaver Builder.

Why I Prefer Creating Modules Over Creating Blocks

Developer Reference

When learning to develop for a new tool one of the most important things is developer/API reference and examples. Both Gutenberg and Beaver Builder have solid developer reference, however in general I feel that Beaver Builder’s is better organized. Its examples in the reference (and the modules within the plugin itself) are also a great source of reference and the vast majority of the time code can be copied directly into your own custom modules and it will work. Conversely, Gutenberg is attempting to remain as developer friendly as possible and has provided reference in ES5 and ESNext (ES6+ and JSX), but there isn’t always example code in both versions, and there isn’t always context surrounding the code letting you know where/how it should be used.

Build Tools

If you’re serious about making Gutenberg blocks it’s all but mandatory to use build tools (node/webpack/babel/etc). Without this your project could end up enqueuing dozens of JS and CSS files, and none of the ESNext/JSX code will run in the browser. Getting your project setup to properly use these build tools is one of the biggest hurdles to get past when first starting out with Gutenberg, especially if you’re not already using them for other projects (such as React). As mentioned earlier I work off of a remote development server so this type of workflow isn’t ideal as I have to build (or have webpack watching my files and auto-build) and then upload them to my remote server to test. This adds an extra step and is less efficient, and if anyone has any recommendations as to how I could improve this workflow please leave a comment!

Alternatively, with Beaver Builder there is no need for build tools as there is no need for ESNext (unless you just really want to use it) or JSX. On top of that, to prevent dozens of JS and CSS files from being enqueued Beaver Builder renders out all of the necessary dependencies for a given page and caches that as a single JS and CSS file on the web server. So, as long as a module has been built correctly it’s as simple as editing your files, and saving them, and Beaver Builder handles the rest.

Programming Language

The vast majority of code for Gutenberg blocks is intended to be in JavaScript. This is fine in many cases, however it also means that any data used in BlockControls or InspectorControls that cannot be derived from the content itself, or is dynamic in nature must be piped to the front-end. So, any existing code bases where the data already exists in PHP must either be modified to make it available on the front-end (possibly by localizing it) or extend the Rest API so that it can be fetched. In an of itself this isn’t a problem, but it can add development time to a project.

Alternatively, Beaver Builder controls are defined in PHP as a series of nested arrays and they can be dynamically built using data already available in PHP, with no need for extending the WP Rest API or making Ajax API calls. This has been beneficial for me in several projects over the years I’ve used Beaver Builder as I was able to take an existing PHP app and build a Beaver Builder module for it with very little code duplication by utilizing the apps existing APIs.

Rigging a Block or Module

In order to setup the skeleton for a block you need to add necessary fields (components/elements) to a BlockControls or InspectorControls component and then setup all necessary event listeners. This is both a pro and a con as it gives you complete control over how everything is setup, but you also need to setup everything to make sure the state is updated as inputs change.

On the other hand, with Beaver Builder, rigging up a module is as simple as creating nested arrays that define the controls and their behavior – the vast majority of the time there is no need to worry about module state or event handling as that’s all taken care of by Beaver Builder itself. Once in a great while I’ve found the need to create my own field types, but that’s been a rarity. It’s so incredibly easy to setup advanced/complex input controls, such as repeatable sets of controls (called forms, that are re-usable throughout a project, in Beaver Builder).

Experience and Familiarity

Without any doubt I have more experience creating modules for Beaver Builder than creating blocks for Gutenberg. This is largely due to Beaver Builder being around several years longer than Gutenberg. Regardless, as open minded, and objective, as I’m trying to be about Gutenberg this experience, and familiarity, creates a natural bias towards Beaver Builder and this is something of which I’m very well aware. The flip-side of this is that once Gutenberg has been around for as long as Beaver Builder it has huge potential to be much more than it is right now.

The End Product

Gutenberg is now part of the WordPress core so it’s incredibly appealing to developers (including myself) to use a standard that is likely to be a part of WordPress for many years to come. On top of that blocks are super portable between instances of WordPress since there are no plugin dependencies. This is an undeniable benefit of Gutenberg over any third-party page builder product. Lastly, there will naturally be more designers, developers, and editors within the community than any plugin could ever hope to attract.

In spite of how I began this review, stating that I didn’t want to directly compare Gutenberg to Beaver Builder, it’s difficult not to when comparing the end product of a block vs a module and the environment in which each resides. Another way of putting it is that the sum of the editing experience is comprised of more than a single block or module, no matter how great they may be, but rather by the experience of using the editor or page builder as a whole. In each of their current states Beaver Builder has immeasurably more flexibility and features than Gutenberg and I know that my custom modules can easily be used in countless different ways.

In the end, I actually do enjoy creating blocks for Gutenberg; I just prefer creating modules for Beaver Builder.

WordPress Gutenberg Review

I think it’s important to know the history of my experience with WordPress in order to understand the basis for opinions, so this is where I will begin my WordPress Gutenberg review. I had my first real introduction to WordPress in 2012 when I made a site for a client that needed an easy to use CMS. My overall impression with WordPress at the time was overwhelmingly positive, however there was one point of contention – the editor. It wasn’t necessarily the fault of the editor as much as it was CMS’s in general, but I was surprised that there wasn’t an easy way to arrange and layout content in anything other than vertically linear. I ended up needing to place some custom HTML markup in the editor as part of the page content, which didn’t meet my goal of all content being easily editable by the site owner.

A little over a year later I once again found myself in the same situation, only this time the goal of all content being easily editable by the site editor(s) and owner(s) was now a requirement as I was working in a distributed environment with many content editors, most of which having no web development experience. I began researching the various ways to extend the editing experience and found it quite lacking – needing to cobble together various plugins, shortcodes, menus, widgets, custom post types, post meta and metaboxes, and custom page templates to make it all work. It did work, however even after training content editors they still struggled to understand how to edit site content and where it all lived within the WordPress admin.

The Rise of Page Builders

A little over a year later I began hearing about new WordPress plugins called Page Builders, such as Visual Composer, Divi, and Beaver Builder. In the end I decided on Beaver Builder and haven’t looked back since. With Beaver Builder, in many cases, I no longer needed other plugins (aside from the core list used on all sites), shortcodes, widgets, custom post types, post meta or metaboxes, or even custom page templates. It allowed me to style the site using brand guidelines and then turn it over to the site content editors where they were able to edit their content on one place, right on the page and on the front-end. It allowed me to separate concerns considerably between the responsibilities of developers and content editors, while still providing the editors with a huge amount of flexibility.

There were those in the WordPress community that looked down on page builders, seeing them as inferior to the custom code ways of the past. I can’t say that I blame them either; many of us had poor experiences with tools like DreamWeaver (or Microsoft FrontPage) and had lost trust in visual editors to build our HTML markup. Despite that, plugins like Beaver Builder worked incredibly well and output clean markup, and from my perspective page builders were obviously the future of website creation and editing in WordPress. There were simply too many benefits to Page Builders for them to not become mainstream.

Finally A New Editor Arrives: Gutenberg

With the rise in popularity of page builder plugins and a plethora of site building services such as Wix, Weebly, and Squarespace, among many others, WordPress needed to do something to stay competitive. The answer to this was: Gutenberg. Now, without any further introduction, here is my review of the Gutenberg editor, organized by role and broken down into pro/con lists.

From The Perspective of a Content Editor


  • User Interface Design: Though it is completely new, the design of the user interface fits very well with the rest of the WordPress admin and should help users to feel comfortable using the new editor.
  • User Interface Responsiveness: Since the entire Gutenberg interface is built using JavaScript it feel quick and responsive, even with dynamic elements.
  • User Interface Standardization: Prior to Gutenberg users may need to work with several different interfaces in order to edit their site, such as menus, widgets, metaboxes, settings pages, etc. With Gutenberg everything can now use the same interface: the block. This isn’t fully implemented yet, as of WordPress 5.0, but it’s already in the works and will drop in the next few major releases.
  • Design and Layout Abilities: Gutenberg offers page-builder-like features for content layout and style. Though relatively limited as of WordPress 5.0 I expect this to expand in the future as the next phase(s) of Gutenberg are implemented and third-party plugins are created.
  • Editor Tools: In order to assist users in crafting higher quality content there are at least two new tools available in Gutenberg. The first is Content Structure, which includes general information about the post and a Document Outline, which helps ensure headings are used properly. The second is a subtle accessibility notice when the color contrast between a block text color and background/cover color isn’t high enough to meet WCAG 2.0 AA or AAA specifications.

All of these things help to bring WordPress at least up to par with competitors, while also preparing it for the future.


  • User Experience:
    • On first impression I was quickly left feeling that it’s rather clunky and requires a lot of clicks to accomplish tasks. This will be explained in further detail below.
    • User Interface elements are hidden until hover/focus/save/etc. There needs to be a balance between keeping the interface simple and clean and showing users what they need, Gutenberg goes a little too far by hiding elements.
      • The block positioning controls (the drag handle) is only visible when hovering on the left 25% of a block. This should always be visible when a block has focus or is being hovered over (regardless of mouse position).
      • The block insert button (small + at the top center of a block) will only show if a block doesn’t presently have focus and if the mouse is hovered along the top edge of the block. The block already doesn’t have focus so the BlockControls will be hidden (and thus won’t interfere with the insert button) so the insert button should be visible regardless of mouse position.
    • When repositioning a block by dragging it up or down the drop-zone isn’t inline with the handle (on the left) so you actually have to move the mouse inward (closer to the center of the blocks), despite the fact that blocks (for the most part) stack vertically (which implies vertical repositioning), which makes the experience feel broken if you simply drag a block straight up and release (as it won’t work).
  • Specific Block Issues:
    • Columns: they’re are incredibly cumbersome to work with (clicking around in just the right spot to finally select the column itself to change its settings is a joke), and blocks within the columns block lose their drag handle so once a block is in a column it’s there for good (or until you delete it and make it again somewhere else). Also, during my time testing the columns block I also experienced a hard crash when I attempted to drag the column block into a drop-zone of the column block that I was moving and my browser tab closed and ended up losing a bit of work that was unsaved. All of this is inexcusable as the columns block is one of the few blocks that give Gutenberg any sort of real flexibility with layout, and will be instrumental in Gutenberg being capable of taking the place of page-builders.
    • List: They don’t allow you to press Tab or Shift+Tab to indent/outdent a list item. This is just a personal frustration that I ran into while creating this list for this review and several times found myself jumping down to the next block (when pressing Tab) when all I wanted to do was indent a list item. Really?
  • Gutenberg on mobile:
    • The Inspector Controls sidebar is full-width, even on something like an iPad (with ample screen space), and covers the page content so changes that are made cannot be previewed until the Inspector Controls are closed. This breaks the user experience, and defeats the whole purpose of having the editor UI built in JS where you can see changes live.

From the Perspective of a Developer, Extending the Editor and Creating Blocks


  • Standardization for development:
    • In the past there was no standardized way of extending the editor, which meant that it was almost entirely up to developers. Though this allows for a more broad spectrum of developers, ranging in skill from beginner to expert, to create extensions it also leads to fragmentation in implementation and severely limits the ability to share code. Conversely, developing for Gutenberg is largely standardized around blocks.


  • High barrier of entry:
    • Getting started developing for Gutenberg can be a fairly daunting task. Though Gutenberg blocks can be created with minimal PHP and ES5 JavaScript the expected standard is to be ES6+ with JSX, which requires some knowledge of React and build tools (Webpack and Babel). If simply creating a series of blocks this can be relatively straight forward, especially if using somethings like create-guten-block, however it can quickly become complicated if the plugin is doing more than creating new, simple/static, blocks.
  • Documentation:
    • Overall, the documentation is well written and fairly thorough, but the way that it’s organized left me not knowing what I didn’t know. Meaning, I didn’t know what to search for within the handbook because I was new to the terminology and the order of the handbook is such that the intermediate/advanced topics are buried within the chapters, coming after the massive list of Packages and Components. This initially left me with the impression that I had gone through all guided documentation that was available, which sent me to Google to fill in the gaps (which has a lot of outdated information as Gutenberg changed so much over its development cycle). There are also some challenges with the docs and examples where some examples are provided in ES5 and ESNext while others are only in ESNext (ES6+ and JSX). The Gutenberg examples provided by WordPress are also a great starting point, but don’t cover things such as the InspectorControls or ServerSideRender. Lastly, looking through the Gutenberg source on Github isn’t as helpful as it could be since that code needs to be built/transpiled so the code isn’t directly usable within your own project, and completely irrelevant if writing it in ES5.
  • Migrating existing projects to Gutenberg:
    • Existing plugin code bases that use PHP to render user input controls (such as for meta boxes, widgets, or shortcodes) must be rewritten in JavaScript, and whatever rendering/template system you’re using will now need to be built in JavaScript as well. Also, if those inputs used dynamic data it now also needs to be piped to the front-end so it can be used in JavaScript, likely via the REST API.

In closing, I think WordPress was in a position where it needed to make a big, bold, change or risk moving towards irrelevance as other more modern competitors eroded away at its market share. There seemed to be some internal confusion, at least early on, about what Gutenberg actually was: whether it was simply a replacement editor or a full site builder that merely begins with the replacing the editor. As the development cycle continued that messaging became more clear, and we now know that Gutenberg, phase 1, is just the first step towards being a full site builder. In my opinion I think it was largely a success, and the majority of the issues that I’ve outlined in this review can be resolved in future releases or by third-parties via plugins. The only exception to that is the development complexity challenges, but this appears to be the direction the web development industry is heading.

That said, I think Gutenberg still has a long ways to go in order for it to be a complete success. It will need to continue to evolve and grow in what it can do, with more and more advanced layout and styling features being added. For instance, as much of a giant leap forward Gutenberg is compared to the classic editor it still pales in comparison to something like the Wix editor.

All of this is a risk and gigantic opportunity for WordPress, and with the foundation in place I’m both hopeful and excited to see where things go from here.

Using a PHP Framework or Library in WordPress Plugins and Themes

Anyone who has spent a fair amount of time creating WordPress Plugins or Themes has likely also come across the need to package a PHP framework or library inside a plugin or theme. On the surface this is a fairly routine thing to do – simply copy the file into your plugin or theme, or use composer. There are lots of plugins out there using various PHP libraries and frameworks.

The Problems Begin

I’ve personally started including a PHP framework that I’ve created to help make development easier and add some features that I repeatedly use from project to project. At first this is great, and development is humming along, but eventually you’ll likely run into some problems, like I did. When WordPress loads it loads each activated plugin alphabetically (based on the plugin directory), so let’s say we have two plugins – one called “Analytics” and one called “Cache” and both include the same “Utilities” framework. When Analytics is loaded it will load the Utilities framework, and when Cache is loaded (depending on how the Utilities framework is built) it will either skip loading Utilities because it’s already been loaded or everything will come crashing down due to “Fatal error: Cannot redeclare class/function”. Assuming everything loaded properly, without any fatal errors, the Utilities framework is now loaded and available for use by Analytics and Cache, and you move on with development.

In a closed system where you control the entire stack, all dependencies, plugins, and themes this isn’t a problem. However, with WordPress the idea is that any number of plugins or themes may be installed by the end user, and in this case the developer of a plugin or theme doesn’t have control over what other dependencies, plugins, or themes get installed. So, back to the example from above, what if Analytics needs version 1.0.0 of the Utilities framework and Cache needs version 2.1.0 of the Utilities framework? Knowing the order in which plugins are loaded we know that the Analytics plugin will successfully load the 1.0.0 version of Utilities that is packaged with it, but Cache will be stuck with version 1.0.0 as well.

Assuming that the framework is just a simple class, one way around this problem is to rename the class based on it’s version, or namespace the framework based on it’s version. The problem with this solution is the implementation within your plugin or theme – each time the framework updates you have to update the calls to the framework, which makes maintenance a complete mess (not only for your plugin or theme but also for the developer of the framework). Making things worse, what if the framework is a package in itself, containing dozens of interface and class files?

As a quick side note, one could argue that the chances of this exact situation happening is quite unlikely. However, I think there’s a strong case to be made for plugin developers who make multiple plugins that are relevant to the same audience actually running into this problem. Especially if the plugin end-users happen to update one plugin (that includes a framework) but not another plugin (thus leaving one of the plugins with an outdated framework).

WordPress Hooks Are Our Friend

The solution that I came up with is similar to what the CMB2 toolkit uses, but is instantiated in a different way and uses namespacing as part of the solution. In my specific situation (using my own framework) I had the following requirements:

  • Ability load two separate version of the framework simultaneously.
  • Allow for the newest version to load in a way that guaranteed backwards compatibility.
  • No need for changing the framework namespace or class names with each version.

What I ended up with is a framework that adheres to the following versioning scheme:

  • Major version (1.0.0 to 2.0.0) releases are namespaced by including /v1/ or /v2/ in the namespace to allow for major version releases to run side-by-side with no conflicts. This allows one plugin to use version 1 while another uses version 2.
  • Minor version (1.0.0 to 1.1.0) releases only add new features (never remove) and do not change the interface of existing classes and methods to guarantee backwards compatibility. This allows plugins that expect an old version of the framework to still run properly with a newer version of the framework.
  • Dot version (1.0.0. to 1.0.1) releases only fix bugs and security issues and never change functionality.

The Code

This addresses version dependency issues, but in order to force the highest version of the framework to load I needed to add an init file. So, in the section of my plugin where all other dependencies are loaded I simply add a line such as this:

require_once 'includes/laubsterboy-sdk/v1/init.php';

Which loads the init.php:


namespace laubsterboy_sdk\v1;

if (!class_exists('\laubsterboy_sdk\v1\Laubsterboy_SDK_Init_1_0_0')) {
	 * Laubsterboy SDK Init class
	 * This class is responsible for loading the latest minor version of the SDK.
	 * This is needed since there is a possibility for multiple plugins including
	 * the SDK and the first plugin activated may not include the newest version.
	 * Anything that breaks backwards compatibility must be placed into a new
	 * major version, and namespaced as such, to allow for multiple versions to
	 * run side by side.
	class Laubsterboy_SDK_Init_1_0_0 {
		protected static $instance = null;
		protected $version = '1.0.0';

		 * Laubsterboy SDK Init Constructor
		 * Is responsible for comparing its version versus the global version and modifying as necessary
		 * @since 1.0.0
		protected function __construct() {
			global $laubsterboy_sdk_v1_version;

			if (empty($laubsterboy_sdk_v1_version) || version_compare($laubsterboy_sdk_v1_version, $this->version, '<')) {
				$laubsterboy_sdk_v1_version = $this->version;

			add_action('after_setup_theme', array($this, 'load'), 1);

		 * Laubsterboy SDK Init Singleton
		 * Retrieves an instance of this Laubsterboy SDK Init class
		 * @since 1.0.0
		 * @return Laubsterboy_SDK_Init_1_0_0
		public static function get_instance() {
			if (is_null(static::$instance)) {
				static::$instance = new static();

			return static::$instance;

		 * load
		 * Performs various checks to see if this version of the SDK should be loaded or skipped
		 * @since 1.0.0
		 * @return void
		public function load() {
			global $laubsterboy_sdk_v1_version;

			// Check to make sure this load method is being called via the after_setup_theme action
			if (!doing_action('after_setup_theme')) return;

			// Check if the global version is the same as this version
			if ($laubsterboy_sdk_v1_version !== $this->version) return;

			// Check if this version has already been loaded
			if (defined(__NAMESPACE__ . '\LAUBSTERBOY_SDK_LOADED')) return;

			// Define the version
			define(__NAMESPACE__ . '\LAUBSTERBOY_SDK_LOADED', $this->version);

			// Load the Laubsterboy_SDK class
			require_once 'laubsterboy-sdk.php';


Lastly, in order to actually use the framework all I need to do is hook into the ‘after_setup_theme’ action, such as this:

function my_plugin_after_setup_theme() {
	// Create SDK instance
	$sdk = new \laubsterboy_sdk\v1\Laubsterboy_SDK();
add_action('after_setup_theme', 'my_plugin_after_setup_theme');

The way all of this works is by each plugin or theme loading the framework init.php file which creates an instance of itself, using the singleton pattern. In the constructor it checks for the existence of a full version global number to compare against. If the current version of the framework is greater than the global version then it hooks into the ‘after_setup_theme’ action and sets the global version to be the same as its version. Lastly the callback for the ‘after_setup_theme’ performs a few checks to make sure that it’s attempting to load the highest version number and that the framework hasn’t been loaded yet, and then finally loads the main framework class.

Ultimately, it’s a fairly simple setup for using a PHP framework or library in a WordPress plugin that’s easy to implement and maintain. This is the solution that worked for me, but I’m sure there are other solutions out there so please share your thoughts, and what you’ve done, in the comments.

Search WordPress Users by Name

If you run a WordPress site with a large list of users and have ever needed to search for a specific user (from the Users > All Users admin page) there’s a good chance no users were found. The problem is that the default query only searches by nicename (username) and email address. However, if you need to search by first name, last name, or a custom user meta field, the default search query is all but useless. Thankfully, the Improved user search in backend plugin fixes this shortcoming, but unfortunately this plugin is outdated and won’t work if you’re running PHP 5.5 and WordPress 3.9 or higher.

So, I’ve gone ahead and created my own user query filter to fix the problem, and included some additional functionality to improve the usefulness of the user search.


* user_search_by_multiple_parameters
* Modifies the wp_user_query to allow for User searching (within the WordPress dashboard > Users > All Users) by:
*	first_name
*	last_name
*	nickname
*	any other custom meta_key added to user profiles (manually or through something like Advanced Custom Fields)
* @param    object  $wp_user_query  a WordPress query object
* @return   object	$wp_user_query  a modified version of the WordPress query object parameter
function user_search_by_multiple_parameters($wp_user_query) {
    if (false === strpos($wp_user_query->query_where, '@') && !empty($_GET["s"])) {
        global $wpdb;

        $user_ids = array();
        $user_ids_per_term = array();

		// Usermeta fields to search
		$usermeta_keys = array('first_name', 'last_name', 'nickname');

		$query_string_meta = "";
		$search_terms = $_GET["s"];
		$search_terms_array = explode(' ', $search_terms);
		// Search users for each search term (word) individually
		foreach ($search_terms_array as $search_term) {
			// reset ids per loop
			$user_ids_per_term = array();
			// add all custom fields into the query
			if (!empty($usermeta_keys)) {
				$query_string_meta = "meta_key='" . implode("' OR meta_key='", $wpdb->escape($usermeta_keys)) . "'";

			// Query usermeta table
            $usermeta_results = $wpdb->get_results($wpdb->prepare("SELECT DISTINCT user_id FROM $wpdb->usermeta WHERE (" . $query_string_meta . ") AND LOWER(meta_value) LIKE '%%%s%%'", $search_term));

            foreach ($usermeta_results as $usermeta_result) {
	            if (!in_array($usermeta_result->user_id, $user_ids_per_term)) {
                	array_push($user_ids_per_term, $usermeta_result->user_id);
			// Query users table
            $users_results = $wpdb->get_results($wpdb->prepare("SELECT DISTINCT ID FROM $wpdb->users WHERE LOWER(user_nicename) LIKE '%%%s%%' OR LOWER(user_email) LIKE '%%%s%%' OR LOWER(display_name) LIKE '%%%s%%'", $search_term, $search_term, $search_term));

            foreach ($users_results as $users_result) {
                if (!in_array($users_result->ID, $user_ids_per_term)) {
                    array_push($user_ids_per_term, $users_result->ID);
            // Limit results to matches of all search terms
            if (empty($user_ids)) {
	            $user_ids = array_merge($user_ids, $user_ids_per_term);
            } else {
                if (!empty($user_ids_per_term)) {
                    $user_ids = array_unique(array_intersect($user_ids, $user_ids_per_term));
		// Convert IDs to comma separated string
        $ids_string = implode(',', $user_ids);

		if (!empty($ids_string)) {
			// network users search (multisite)
			$wp_user_query->query_where = str_replace("user_nicename LIKE '" . $search_terms . "'", "ID IN(" . $ids_string . ")", $wp_user_query->query_where);
			// site (blog) users search
            $wp_user_query->query_where = str_replace("user_nicename LIKE '%" . $search_terms . "%'", "ID IN(" . $ids_string . ")", $wp_user_query->query_where);
            // network/site users search by number (WordPress assumes user ID number)
            $wp_user_query->query_where = str_replace("ID = '" . $search_terms . "'", "ID = '" . $search_terms . "' OR ID IN(" . $ids_string . ")", $wp_user_query->query_where);

    return $wp_user_query;
add_action('pre_user_query', 'user_search_by_multiple_parameters');



This can simply be dropped into your theme’s functions.php file, or can be used to create a plugin. It will work as is, but if you have custom user meta fields, possibly added using Advanced Custom Fields, you can simply add the field key to the $usermeta_keys array to include it in the user query.

WordPress Menu Anchor

I recently had the need to add a series of anchor links to a WordPress menu that linked to specific sections of a page. I found this to be tedious, since the page URL needed to be hard coded into the custom link menu item and if the page URL was ever updated each anchor needed to be updated as well. To complicate things further, when looking at the custom link within the menu editor it’s not immediately obvious that the link is an anchor if the URL is longer than the input box.

What I wanted to be able to do is simply create a custom link menu item and set the link value to #my-custom-anchor. Generally if you create a custom link menu item and set the link to be something like #my-custom-anchor it will work, if you’re already on the page for the given anchor, however it will also navigate to “my-custom-anchor” even if you’re on another page where “my-custom-anchor” doesn’t exist.

What I needed was for the anchor to navigate to the desired page and then to the specific section of the page. To do this, the URL would need to have the page URL prepended to the anchor hash. This would allow anchor links to be clicked from anywhere on the website and still navigate to the correct page, and correct section, but if the page was already being viewed the page would not reload (so scrolling animations would still work as well).

Since all of the anchor links were nested under a page menu item, as illustrated in the example below, I was able to filter the menu and prepend the URL with the URL of its’ parent menu item.

Menu Structure Example

  • Page Menu Item 1
    • Page Section 1 Anchor Menu Item
    • Page Section 2 Anchor Menu Item
      • Page Section 2 Sub Section 1 Anchor Menu Item
      • Page Section 2 Sub Section 2 Anchor Menu Item
    • Page Section 3 Anchor Menu Item
  • Page Menu Item 2
  • Page Menu Item 3

In the above example each “Page Section… Menu Item” would link to “Page Menu Item 1” and scroll to the specified section of that page. This is very useful for long pages with many sections and sub-sections.

The Solution is in the Code

To accomplish this I created a menu filter function, that gets added to the themes functions.php file, that searches for menu items with URLs that begin with a # and then prepends the URL with the URL of its’ parent menu item.

function lb_menu_anchors($items, $args) {
	$urls = array();
	$custom_anchor_links = array();
	foreach ($items as $key => $item) {
		$urls[$item->ID] = $item->url;
		if ($item->object == 'custom' && substr($item->url, 0, 1) == '#') {
			$custom_anchor_links[] = $item;
	foreach ($custom_anchor_links as $custom_anchor_link) {
		if (strpos($urls[$custom_anchor_link->menu_item_parent], '#') === false) {
			$custom_anchor_link->url = $urls[$custom_anchor_link->menu_item_parent] . $custom_anchor_link->url;
		} else {
			// multiple nested menu items with anchors
			$custom_anchor_link->url = explode('#', $urls[$custom_anchor_link->menu_item_parent])[0] . $custom_anchor_link->url;
	return $items;
add_filter('wp_nav_menu_objects', 'lb_menu_anchors', 10, 2);

This allowed me to create custom link menu items with easily readable anchor links, that could be nested, and would also dynamically update if the page URL ever changed. Another benefit to this method vs “hard coding” an anchor link menu item is that the URL continues to work in a Domain Mapped environment, and across dev, staging, and production environments as well.

WordPress Check if a Menu is Empty

While working with WordPress there are times that it can be very useful to check if a menu is empty before outputting markup. One example is for displaying dynamic, custom, menus in a sidebar where you may not want to output any markup if the menu is empty. This is actually the default functionality of the wp_nav_menu method, but generally menus are wrapped in modules and if the menu is empty one may want to omit the entire module. Since wp_nav_menu will return false if echo is set to false and the menu is empty we can use this with a simple conditional statement to determine if the menu module markup should be output or not.

if (wp_nav_menu( array( 'theme_location' => 'secondary', 'echo' => false )) !== false) {
    // This is where your menu module would go
    wp_nav_menu( array( 'theme_location' => 'secondary' ));

Its a rather simple solution that just requires a solid understanding of the underlying functionality built into the nav-menu-template.php WordPress core file.

WordPress Custom Sectional Menu

WordPress Menus

With the release of WordPress 3.0 menus were introduced as a visually editable element within the dashboard, dramatically improving WordPress’ CMS capabilities. However, many large websites require menu systems that are a bit more flexible and dynamic that what the built-in menu system provides. For instance, have you ever needed to create a primary navigation menu that resolved to top-level sections of the website and a series of secondary navigation menus that resolved to sub-pages related to each top-level section? Sure, you can create one menu for the top-level primary navigation and another menu for each sub-section of the website and then create a page template corresponding to each of the sub-section menus. The problem with this approach is that you have to create and maintain so many different menus and page templates, not to mention if you’re planning to turn the site over to a client upon completion it requires them to learn and follow certain steps with each page that they create. What if, instead, we could create one master menu and use the regular page template? This is where a custom sectional menu comes in by use of the wp_nav_menu_objects filter hook.

Custom Sectional Menus

To do this we need to create a large nested menu, resembling something similar to the list below, and then set it to be the active menu for the primary and secondary theme locations.

  • top-level-menu-item1
    • sub-section-menu-item1
    • sub-section-menu-item2
    • sub-section-menu-item3
      • nested-sub-section-menu-item1
  • top-level-menu-item2
  • top-level-menu-item3
    • sub-section-menu-item1
    • sub-section-menu-item2
      • nested-sub-section-menu-item1
      • nested-sub-section-menu-item2
      • nested-sub-section-menu-item3

Using the nested menu example from above the primary navigation menu would always show the top-level-menu-items. However, when viewing a sub-section page, such as the page associated with “nested-sub-section-menu-item3” the secondary menu would only show the menu items that are nested under “top-level-menu-item3”. The only remaining question is, how exactly do we do this?

The Solution

I’ve put together a fairly simple function snippet that can be copied and pasted into your themes functions.php file.

function lb_sectional_menu($items, $args) {
	// theme_locations to filter
	$locations = array('secondary');
	// include the root parent menu item in the menu (true) or not (false)
	$display_parent_menu_item = false;
	if (in_array($args->theme_location, $locations)) {
		$allow_menu_items = false;
		foreach ($items as $key => $item) {
			if ((int)$item->menu_item_parent === 0) $allow_menu_items = false;
			if ((int)$item->menu_item_parent === 0 && ($item->current || $item->current_item_parent || $item->current_item_ancestor)) $allow_menu_items = true;
			if ($allow_menu_items === false || ((int)$item->menu_item_parent === 0 && $display_parent_menu_item === false)) unset($items[$key]);
	return $items;
add_filter('wp_nav_menu_objects', 'lb_sectional_menu', 10, 2);

Update September 17, 2014 – I’ve updated the lb_sectional_menu filter function to be much more efficient and less prone to error. The wp_nav_menu_objects filter is applied after all menu_items have been sorted/ordered so instead we can just look for menu_items with a menu_item_parent that is equal to zero (meaning that it’s a root parent menu_item) and allow menu_items until the next menu_item_parent equal to zero is encountered. This means the menu will work even if it’s a page, post, tag, custom link, etc. It will also work no matter how many menu items are nested.

This function allows you to build a single, nested, menu and then reuse it across the entire website, where it will dynamically display the necessary menu items for the section being viewed.