DevTips – Namespaces in PHP

Published in WordPress.

Watch our video

There is a better version of your web

Share this post

About a year ago WordPress decided to update the required minimum PHP version, from 5.2 (used since 2010) to something more up-to-date. In fact, Today the minimum version of PHP recommended by WordPress is one of the most recent: PHP 7.3.

If you are a simple WordPress user, this probably will not impact you too much (beyond the fact that these new versions give better performance).

But if you are a developer, these new PHP versions have some awesome features you can use in your plugins and themes. And today, specifically, I would like to talk to you about one that has been with us for a long time but: namespaces.

WordPress and code prefixes

One of the first rules you learn as a WordPress developer is to “use prefixes in everything we do” to avoid “name collisions.” As we can read in WordPress best practices :

A naming collision happens when your plugin is using the same name for a variable, function or a class as another plugin.

[To avoid name collisions], 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.

Best practices for developing WordPress plugins

Thus, for example, instead of creating a function like get_site_id, it’s better to name it nelio_content_get_site_id. This way, we are able to quickly identify the plugin (nelio_content) or theme to which a certain function (get_site_id) belongs and avoid fatal errors if several plugins try to define the same function.

Using prefixes is a rudimentary way of creating a “namespace”; a workaround we had to implement when we didn’t have a better alternative. All those elements that use the same prefix are part of the same set or namespace. But this results in unnecessarily more complex code: names are longer because of prefixes that serve no purpose other than emulating namespaces.

PHP Namespaces

PHP version 5.3 introduced the concept of namespace. The definition they give of it in the documentation seems excellent to me, so I reproduce it here:

In the broadest definition namespaces are a way of encapsulating items. This can be seen as an abstract concept in many places. For example, in any operating system directories serve to group related files, and act as a namespace for the files within them. As a concrete example, the file foo.txt can exist in both directory /home/greg and in /home/other, but two copies of foo.txt cannot co-exist in the same directory.

In the PHP world, namespaces are designed to solve two problems that authors of libraries and applications encounter when creating re-usable code elements such as classes or functions:

1. Name collisions between code you create, and internal PHP code or third-party code.

2. Ability to alias (or shorten) Extra_Long_Names, improving readability of source code.

PHP docs

How to create a namespace

Creating a namespace in PHP is extremely easy. At the beginning of the PHP file you create, add a namespace directive with the name you want to use and “everything” you define in that file will belong to that namespace:

<?php
namespace Nelio_Content;

Yes, it’s that simple! Now “everything” we create there will be in the Nelio_Content namespace. For example, if I define a function like the one I mentioned at the beginning:

<?php
namespace Nelio_Content;

function get_site_id() {
  // ...
}

we now know that get_site_id is inside the Nelio_Content namespace. In this way, we no longer have to use the nelio_content_ prefix when defining the function. Great!

Exceptions To Namespaces

If you look closely at what I have told you so far, you will see that I have been writing “everything” in quotes: “‘everything’ we add there will belong to the specified namespace.” Why did I do that? Because namespaces don’t apply to absolutely all code we write… there are some exceptions.

PHP namespaces only cover the following PHP elements:

  • Classes
  • Interfaces
  • Traits
  • Functions
  • Constants declared with const but not with define

In addition, there are some additional things in WordPress that also need their own namespaces and, unfortunately, PHP namespaces do not cover: your script handles, database options, or custom content types and their metadata, etc. In all these cases, you must continue using prefixes.

How to Import Elements From One Namespace To Another

If you need to use an element that is in your own namespace, you don’t have to do anything special: just call it by its name. For example, in the following code snippet:

<?php
namespace Nelio_Content;

function get_site_id() {
  // ...
}

function get_auth_token() {
  $site_id = get_site_id();
  // ...
}

You can see that we have defined two functions: get_site_id and get_auth_token, both within the Nelio_Content namespace. When get_auth_token needs to use get_site_id, it simply calls it as usual.

If, on the other hand, you need to use get_site_id in a different namespace, you must call the function using its full identifier:

<?php
namespace Something_Else;

function do_some_action() {
  $site_id = Nelio_Content\get_site_id();
  // ...
}

or you must import the function with the keyword use:

<?php
namespace Something_Else;

use Nelio_Content\get_site_id;

function do_some_action() {
  $site_id = get_site_id();
  // ...
}

I personally like the second option a lot: using the keyword use to import functions from other namespaces, you can take a quick look at the header of your file and identify its dependencies.

WordPress Filters And Actions With PHP Namespaces

There is an important detail that you should keep in mind when using namespaces next to WordPress filters and actions. When you specify filter and action callbacks, usually you do so by giving the callback name as an string:

<?php
// ...
add_action( 'init', 'do_some_action' );

The problem is that if this function is within a namespace, the previous hook will not work as expected; you must tell WordPress the full name of the function. In other words, you have to include its namespace (if it has one).

Are you adding the hook in the file where you define the namespace itself? It doesn’t matter, use the full name:

<?php
namespace Nelio_Content;

function do_some_action() {
 // ...
}
add_action( 'init', 'Nelio_Content\do_some_action' );

Are you in another namespace but you imported the function with use? It doesn’t matter either, use the full name:

<?php
namespace Something_Else;

use Nelio_Content\do_some_action;
// ...

add_action( 'init', 'Nelio_Content\do_some_action' );

Using Aliases With Our Namespaces

Another very interesting functionality of namespaces is aliasing. Imagine the following scenario:

<?php
namespace Nelio_Content;

function get_site_id() {
  // ...
}

If I want to use this function in another namespace, we have already seen that I can do it with use. But how would I use this function if the module I want to use it in already has a function called get_site_id?

Well, luckily for me, we can alias our imports into new names:

<?php
namespace Something_Else;

use Nelio_Content\get_site_id as get_nc_site_id();

function get_site_id() {
  // ...
}

function do_some_action() {
  $nc_site_idd = get_nc_site_id();
  // ...
}

Start Using Namespaces Today!

Namespaces are a fantastic tool to avoid name collisions and to organize our code. In fact, and although I have not commented on this post, there are standards such as PSR-4 that allow PHP to auto-load classes based on the structure of namespaces you use and how you organize the code into directories and files.

If you are not yet using namespaces in your projects yet, we recommend you start doing so from now on. Tell us about your experience in the comments!

Featured image by Chaitanya Tvs on Unsplash.

Leave a Reply

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

I have read and agree to the Nelio Software Privacy Policy

Your personal data will be located on SiteGround and will be treated by Nelio Software with the sole purpose of publishing this comment here. The legitimation is carried out through your express consent. Contact us to access, rectify, limit, or delete your data.