One of the loved WordPress features is: how easy is to install and use 3rd party plugins to enhance our experience. And there are more than 55k plugins we can choose from! Cool, isn’t it?
Is so cool that some users go crazy and start installing too many of them, but this is not what we’re talking about 🙂

The uniqueness problem

As a WordPress developer, we want to create a plugin and (maybe) publish it. And so, we want to be sure that our function and class names won’t clash with other plugins installed.

So, In this article, we’re going to see two methods to do so. In the specific, we’re going to compare the:

  • old fashion way of prefixing
  • PHP namespace

The prefixing namespace

I and many others have used this approach for years and, to me, never caused any conflict. It is a reasonable method, but it has its own problems and also is out to date.

All variables, functions and classes should be prefixed with a unique identifier. Prefixes prevent other plugins from overwriting your variables and accidentally calling your functions and classes. It will also prevent you from doing the same.

https://developer.wordpress.org/plugins/plugin-basics/best-practices

For the records: Let’s don’t forget that real namespaces were only introduced in 2009, six years after the first WordPress release. And also for many years later, some hosting service were still using PHP versions < 5.3. So prefixing was a good practice back then, but personally seeing this suggested as best practice in 2020 feels a bit wrong.

Anyway, let’s follow this practice.

register_activation_hook( __FILE__, 'pluginprefix_function_to_run' );

function pluginprefix_function_to_run() {
 ... // do something
}

This is quite a common problem: doing some initialisation when we first activate the plugin. In this example, take from the WordPress website, the prefix chosen is pluginprefix_.

What’s wrong with that?

  1. Does not guarantee at all that’s unique
  2. Add distracting noise
Uniquity

Doesn’t really matter how much fantasy we put in to choose a cool prefix, there is no real guarantee that someone else will have the same idea.

Funny enough, once I’ve met a person with my same name and surname, so I already know that using alessandro_senese_ as a prefix doesn’t guarantee me uniquity.

Another problem we have is length and memorability. If I should prefix my functions with my name and surname, it’s at least 16 characters to type every time. Even my nickname ceceppa_ would be 7 characters.
Also, I should make them a bit unique for the project, for example: cececeppa_muu_init, where muu is a hypothetical project name.

I know how to solve the issue: Make it short!

That’s the common solution adopted, so I could use: cmuu_ or ceppa_muu_.

Yeah, that might work, but…

The noise

Noise is unwanted sound judged to be unpleasant, loud or disruptive to hearing. From a physics standpoint, noise is indistinguishable from sound, as both are vibrations through a medium, such as air or water.

https://en.wikipedia.org/wiki/Noise

ME: But we’re talking about code, not sound here!

ME: But we’re talking about code, not sound or physics!

ME: I know, I know. Let me finish

Let’s rephrase for our purpose:

Noise is unwanted code, disruptive to reading. From readability standpoint, noise is indistinguishable from code.

“Me”

I haven’t invented the word Noise, and you’ll hear more and more when you start caring about readability. But I couldn’t find any definition, so I’ve made up one 🙂

Let’s compare some with and without prefix:

With prefix

function myfirsttheme_setup() { ... }

function ceceppa_muu_on_plugin_activated() { ... }

function ceceppa_muu_function_a() { ... }
  • 👍 the function name is unique
  • 👎 is camouflaged with the function name
  • 👎 forces us to mentally separate it from the rest of the function name, to figure out what’s it does
  • 👎 is unique to the project, and cannot be easily reused across different projects
  • 👎 you cannot have another function with the same name

Without prefix

function theme_setup() { ... }

function on_plugin_activated() { ... }
  • 👍 there is no cognitive load
  • 👍 the function name is already self explaining
  • 👎 the function name is not unique, it could clash with other plugins

NOTE: For unique I intend the possibility of clashing with 3rd party plugins or themes!

As we have seen using prefix does solve this problem but also introduces new ones, that affect our code readability.

2. The namespace

What are namespaces? In the broadest definition namespaces are a way of encapsulating items.

php.net

So, basically, like prefixing, a namespace is used to prevent name collisions within your or 3rd party functions.

The main difference with prefixing, is that namespace is defined, a the top of each file, using the namespace keyword.

namespace MyWonderfulTheme;

function theme_setup() {...}

function do_something_cool() { ... }

Now all the functions within the same file have the same MyWonderfulTheme namespace. This means that we can use the same function name with a different namespace:

namespace MyAmezingPlugin;

function on_plugin_activated() {...}

function do_something_cool() {...}

In this example, the two do_something_cool function names do not clash with each other, because they have a different namespace. The full signature for each function is:

MyWonderfulTheme::do_something_cool {...}

MyAmezingPlugin::do_something_cool {...}

Make it esplicit

Another advantage of using a namespace is that’s only specified once, at the top of each PHP file. So you can get as much as creative you want, there is no need to came up with cryptic short names, just to save a few characters.

Much like directories and files, PHP namespaces also contain the ability to specify a hierarchy of namespace names. Thus, a namespace name can be defined with sub-levels:

https://www.php.net/manual/en/language.namespaces.nested.php

namespace MyProjectSubLevel;

Use namespace

With namespace, there are few differences to consider when to want to access to a function or a class.

Same file namespace

Inside the same file a function (or class) can call each other without the need of specifying the prefix.

namespace TestNamespace;

function function_a() {
...
}

function function_b() {
    function_a();
}

Access from another file

If we have two or more files with different namespaces, to access each other function/class we have to specify the full prefix to do so:

  • Namespace1
namespace Namespace1;

function function_a() {
    Namespace2function_b();
}

function function_b() {
}

To access a different namespace we have to prepend the backslash symbol

  • Namespace2
namespace Namespace2;

class TestClass() {
}

function function_b() {
    SubLevelfunction_b();
}

When accessing a sub-namespace, we can omit the part in common

  • Sub-level of Namespace2
namespace Namespace2SubLevel;

function function_a() {
}

function function_b() {
}

function function_c() {
    new Namespace2TestClass();
}

There is no shortcut to access a parent namespace, but we have to specify the full namespace

Namespace: Aliasing/importing

The ability to refer to an external fully qualified name with an alias, or importing, is an important feature of namespaces. This is similar to the ability of unix-based filesystems to create symbolic links to a file or to a directory.

https://www.php.net/manual/en/language.namespaces.importing.php

As we have seen, to access a function or class from a different namespace we have, each time, specify the full signature. This can be very annoying, but don’t worry we can use the use keyword to simplify our life 🙂

Functions
use function \[FULL NAMESPACE\]\[Function name\]
use function \[FULL NAMESPACE\]\[Function name\] as \[ALIAS\]

Example

namespace Namespace1;

use function Namespace2function_a;
use function Namespace2Sublevelfunction_a as another_function;

// equivalent to: Namespace2function_a();
function_a();

// equivalent to: Namespace2Sublevelfunction_a();
another_function();

Aliasing allows us to use a function with a different name

Classes
use \[FULL NAMESPACE\]\[CLASS NAME\];
use \[FULL NAMESPACE\]\[CLASS NAME\] as \[ALIAS\];

Example

namespace Namespace1;

use Namespace2ClassName;
use Namespace2SublevelClassName as AnotherClass;

// equivalent to: new Namespace2ClassName();
new ClassName();

// equivalent to: new Namespace2SublevelClassName();
new AnotherClass();

Aliasing allows use to use a class with a different name

Namespace aliasing
use \[FULL NAMESPACE\] as \[ALIAS\]

Example

namespace Namespace1;

use Namespace2 as N2;

// equivalent to: Namespace2::function_a();
N2::function_a();

We cannot use the aliased namespace to import another namespace, for example the following code won’t work:

namespace Namespace1;

use Namespace2 as N2;
use function N2Sublevel::function_a;

// Undefined function 'N2Sublevel::function_a'
function_a();

If you, like me, use VSCode and don’t like to type or remember the namespaces every time, you can use the PHP Intelephense addon. It will automatically add the namespace import in the first PHP block available.
For example, we can have to type only function_a:

Showcasing Intelliphense autoimport

Intelephense addon in action

The __NAMESPACE__ magic keyword

Another thing to consider, when working with namespaces, is that for filters and hooks we have to pass the full signature of the class / function we want to call.

  • 👎 Doesn’t work: The function initialise will never be called
namespace Namespace1;

add_filter( 'init', 'initialise' );
add_filter( 'init', [ 'TestClass', 'init' ] );

function initialise() {
}

class TestClass {
    public static function init() {

    }
}
  • 👍 Works: We always have to specify the full signature, and the use keyword won’t help us in this case
namespace Namespace1;

add_filter( 'init', 'Namespace1\\initialise' );
add_filter( 'init', [ 'Namespace1\\TestClass', 'init' ] );

function initialise() {
}

class TestClass {
    public static function init() {

    }
}

But we don’t want type the namespaces everytime! – All of us

I agree and don’t worry, PHP help us with the __NAMESPACE__ magic keyword:

namespace Namespace1;

add_filter( 'init', __NAMESPACE__ . 'initialise' );
add_filter( 'init', [ __NAMESPACE__ . 'TestClass', 'init' ] );

function initialise() {
}

class TestClass {
    public static function init() {

    }
}

Cool, isn’t it? Also if we change the namespace name both filter will still work!

Access global classes

The last thing we have to consider when working with namespaces is that global WordPress classes and functions belong to the root namespace. And so to access them we have to prepend the backslash sign:

  • 👎 Doesn’t work: WP_Query is not in the same namespace
namespace Namespace1;

get_post_meta(...)

$posts = new WP_Query(...);
  • 👍 Works: We need to prepend the backslash to access global namespace
namespace Namespace1;

get_post_meta(...)

$posts = new \WP_Query(...);

Conclusions

As we have seen PHP Namespace provides more benefits than the old fashing prefixing. It’s easy to use and make our code cleaner.

Also, if in future we want to work/experiment with a PHP framework, like Laravel, Symphony, etc… We definitely need to get familiar with namespaces!