What “Namespaces” Mean for WordPress Developers

namespaces for WordPress developers

It’s not uncommon for people, especially those new to a knowledge-area, to hear a word bandied about a lot and never really explained. I think “namespacing” is one of those words, and more importantly, it has two rather different meanings that you may need to know as a WordPress developer. So our goal is those two meanings, and then some of the implications of the more interesting version.

The TL;DR

Before we go too deep, an executive summary. “Namespaces” refer to one of two related concepts in WordPress development, both of which are about controlling the meaning and impact of a value, function, or object. The two common versions are:

  1. A “poor person’s” namespace, where you write functions, option values, classes, etc., with some few-letter prefixes, like wpshout_get_value(), 'wpshout_option' or WPShout_Awesome_Class. These are a “userland” ways to avoid naming conflicts (more on that word shortly), and you’ll see them commonly in our and other tutorials about WordPress development.
  2. A PHP language-level namespace, which are much less common in WordPress development (we’ll explain why later), where the language itself infers semantic meaning and impact from the use of a namespace keyword. These look like a file which starts something like this:
<?php 
namespace WPShout;
class Awesome_Class {

}
?>

We’ll go into much more detail about what we mean about each through the rest of the article. So let’s get to it.

Prefixes: Userland Namespacing and WordPress

WordPress is, speaking on the timescale of the internet, quite an old piece of software. First released in 2003, it was created when PHP 4.3 was the latest and greatest. PHP 4.3 was before PHP even had objects in a way that modern PHP developers expect in the 5.x language, and well before the ideas of namespaces to isolate and protect code from naming collisions was added to the language. For further reference, you’re probably running PHP 5.4 or higher on your WordPress site, 5.6 is considered “current”, and PHP7 — because they’re skipping 6, like Microsoft went 7-8-10 for Windows — is coming out before the end of the year (2015).

If you try to create a function that presents a naming conflict, PHP will get mad at you for very good reason.

In your time writing PHP, you may have experienced a naming conflict. If not, what happens is when you try to create a function called do_thing() and there is already a PHP function declared with that name, PHP gets mad at you. This is for a very good reason: if it were easy to create two functions with the same name and different behavior, things would regularly act in confusing ways. But WordPress — especially with a giant ecosystem of plugins — has a lot of different people writing lots of different functions, many of whom may have thought creating a function called run() was a perfectly good idea.

To combat this issue of people’s WordPress sites exploding because of conflicting run() function declarations, the community collectively began adopting and advocating the practice of “namespacing” functions. So that WPShout’s run() became wpshout_run(), while My Awesome Plugin might have been called map_run(). (Initialisms are a common way to find your “namespace.”) These are both examples of “userland” namespaces; “userland” is a term programming folks use to say “not the language, but by users of the language.”

PHP 5.3 was the first version which supported namespaces at the language level

These “namespaces” were reasonably common everywhere before PHP 5.3 came out. PHP 5.3 was the first version which supported namespaces at the language level. But userland namespaces are still very relevant. To this day, WordPress itself and most of its plugins and themes try to continue running on PHP 5.2, which means those sites still don’t support the other type of namespaces.

Generally, this kind of “namespacing” has let WordPress get quite far, and it’s still the more common way you’ll hear the term used in the WordPress sphere. It’s a good idea to do it if you’re writing functions, classes, option values, etc: make sure they start with a memorable, short, and unique slug like wpshout_ or, more likely, a condensed version of your theme or plugin’s name. So do that!

PHP Namespaces: What They Mean and What They Do

Just as the “poor person’s” or “userland” namespaces are about preventing problems, PHP namespaces are too.

As PHP started to become a more friendly object-oriented language, people started to ask for more features common in other object-oriented languages. Namespacing has existed for decades, and its basic role is to allow you to name a class exactly what you want — like User rather than WPShout_User — and let other people using the same system also register a class with the same name. Namespaces essentially isolate your classes and functions. So long as your name is unique per namespace, no complaints or explosions will come from PHP.

As long as your name is unique per namespace, no complaints or explosions will come from PHP

In this way, it’s useful to think of PHP namespaces like isolated folders in a filesystem. That is: just as you can have infinite FirstDraft.docx files and you won’t hear a complaint unless you put them in the same folder, you can infinite run() functions and they’re fine as long as they don’t share a namespace. So as folders are containers in a filesystem, namespaces are containers in PHP.

So in modern PHP, I can have a “WPShout user” represented by the class WPShout\User and it can run side-by-side with a PressUpInc\User. If I want to reference on inside the other (or somewhere else) I refer to it by that full name and it’s clear which I mean. But when I’m writing WPShout related behavior, and my code is in the WPShout namespace, I can simply refer to my classes by their short name.

An Actual Code Example of PHP Namespaces

We just gave a very short summary of using namespaces, but I find it really helpful to see that kind of stuff in action. Here’s the basic syntax for a namespaced WPShout User class:

namespace WPShout;
class User {
    // methods and properties here
}

And beside it, a “PressUpInc” User class could look like:

namespace PressUpInc;
class User {
    // methods and properties here
}

Let’s say that our WPShout\User‘s bill_user method — no, this isn’t a secret hint that we’re going to start charging for things — needed instances of PressUpInc\User and WPShout\ChargingMoneyService. That method could look something like:

namespace WPShout;
class User {
    public function bill_user( $amount ) {
        $pressup_user = new \PressUpInc\User( $this->email );
        $billing_service = new ChargingMoneyService;
        // stuff is done here...
    }
}

If we’re able to put aside how hard it is to fathom quite why we’d need all this stuff here, this code makes a couple important points about PHP (5.3+) namespaces:

  1. They’re mostly used in class-based code. Procedural or function-heavy code can use them, but generally doesn’t today.
  2. Your whole file is considered to be “located in” the namespaces it declares at the top. As such, when you need a class in the same namespace, you can just refer to it without any sort of preamble. This is what we’re doing with new ChargingMoneyService.
  3. When you need to reference classes outside of your current namespace, you use something that resembles a “full file path” way of referring to it. You prepend the name of what you want with a \ to say “treat this as root-relative” and then you give the rest of the namespace “path.” We’re doing this when we write new \PressUpInc\User.

One last note that this code doesn’t show, but is essential to start to understand PHP namespaces is that you can “alias” other classes via the use keyword. So our last snippet could instead look like:

namespace WPShout;
use \PressUpInc\User as PU_User;
class User {
    public function bill_user( $amount ) {
        $pressup_user = new PU_User( $this->email );
        // stuff is done here...
    }
}

What this has changed is that we’re pulling in the \PressUpInc\User in the second line rather than where we want to use the class. Then we’ve aliased it to PU_User. That’s then the name we use in the rest of our code. Frequently people won’t actually use the aliasing part of a use statement, because the class names don’t overlap. Because we’re referring to a foreign User class inside our own, however, it’s essential. (That is, the line use \PressUpInc\FunnyClass; would make that class accessible to us with a simple new FunnyClass();.)

Why PHP Namespaces Matter

The big reason that most PHP developers finally come to understand PHP-level namespaces is because they’re super useful when you’re working with code by other people. There are a few reasons for that, which could be expounded upon at some length. The very short version of those reasons is:

  • Namespaces let other people’s code work nicely with yours in basically the same way that the userland namespaces of the WordPress ecosystem let you run hundreds of plugins on a single site.
  • Autoloading, which is a really nice way to not need to write dozens or even hundreds of include or require statements in your code when it grows large is made easier with namespaces. You can write code that expects a folder location based on a namespace (in line with the conceptual similarity we mentioned earlier) and then loads the file in question just as you need it.
  • Pulling in, and autoloading, other peoples code (called “packages” in the community) with Composer is practically the first step in any non-WordPress PHP project. In this context, that code is virtually guaranteed to be namespaced and autoloaded using either the older PSR-0 or current PSR-4 standard.

Those three benefits, taken together, are why it’s so useful — essential even — to understand what PHP namespaces are. They let you be massively more productive in basically the same way that plugins make you massively more productive in making a WordPress site.

Now You Understand “Namespaces”

So we now understand that namespaces come in two basic varieties: the simple prepend-stuff-to-the-name version that’s more common in WordPress, and the PHP language-level version that’s more common outside of WordPress. In both cases, namespaces’ purpose is to safely allow more code to inter-operate and prevent PHP explosions in your lap. So either version is a very, very good thing. Happy hacking!

Image credit: Noel Lopez via Unsplash


6 Responses

Comments

Pingbacks