Namespaces are similar to satellites in orbit. Every satellite in space has an orbit, and just like satellites, code can’t occupy the same orbit without causing a collision. Satellites are carefully positioned in space to avoid collisions and interference with other satellites. However, a malfunction or a rogue launch into space could put other satellites at risk. Should one of them collide with another, the results would be catastrophic.
Collisions and code
Let’s take a function called get_field
. The function is from a widely popular custom field plugin called Advanced Custom Fields (ACF for short). Imagine you have ACF installed on your WordPress install. Now imagine installing or updating a plugin that also has get_field
as a function. You’d have a collision. And the result would be a fatal error, possibly taking down your site. Catastrophic.
Just as you can’t have a satellite occupy the same spot as another, you can’t have the same function or class declared multiple times and be running at the same time.
Introducing namespaces
This is where namespaces come in. Just as satellites are uniquely identified down to their orbit, namespaces provide an identity for your code, allowing you to group related functions and classes together and keep them organized under one umbrella. By using namespaces in PHP, the risk of colliding with someone else’s code is significantly minimized.
Each namespace acts like a label or tag that you can use to identify and access specific functions and classes without worrying about naming conflicts with other code. This means no more having to prefix functions or classes.
One common misconception about namespaces is that you need some sort of autoloader or class-based structure to use them. This not the case if you have a simple plugin structure.
Adding namespaces to an example plugin
Let’s take a simple plugin that creates an admin panel from prefixed functions.
<?php
/**
* Plugin Name: My Simple Plugin
* Description: A simple WordPress plugin that adds an admin panel.
* Version: 1.0
* Author: Your Name
* License: GPL2+
*/
// Add the admin menu item.
add_action( 'admin_menu', 'my_simple_plugin_add_admin_menu' );
// Define the function that adds the admin menu item.
function my_simple_plugin_add_admin_menu() {
add_menu_page(
esc_html__( 'My Simple Plugin', 'my-simple-plugin' ),
esc_html__( 'My Simple Plugin', 'my-simple-plugin' ),
'manage_options',
'my-simple-plugin',
'my_simple_plugin_render_admin_page'
);
}
// Define the function that renders the admin page.
function my_simple_plugin_render_admin_page() {
?>
<div class="wrap">
<h1><?php esc_html_e( 'My Simple Plugin', 'my-simple-plugin' ); ?></h1>
<p><?php esc_html_e( 'Hello, world!', 'my-simple-plugin' ); ?></p>
</div>
<?php
}
Code language: PHP (php)
With a namespace, we don’t need to prefix the functions. Let’s rewrite the above code to include namespaces.
<?php
/**
* Plugin Name: My Simple Plugin
* Description: A simple WordPress plugin that adds an admin panel.
* Version: 1.0
* Author: Your Name
* License: GPL2+
*/
namespace MySimplePlugin;
// Add the admin menu item.
add_action( 'admin_menu', __NAMESPACE__ . '\add_admin_menu' );
// Define the function that adds the admin menu item.
function add_admin_menu() {
add_menu_page(
esc_html__( 'My Simple Plugin', 'my-simple-plugin' ),
esc_html__( 'My Simple Plugin', 'my-simple-plugin' ),
'manage_options',
'my-simple-plugin',
__NAMESPACE__ . '\render_admin_page'
);
}
// Define the function that renders the admin page.
function render_admin_page() {
?>
<div class="wrap">
<h1><?php esc_html_e( 'My Simple Plugin', 'my-simple-plugin' ); ?></h1>
<p><?php esc_html_e( 'Hello, world!', 'my-simple-plugin' ); ?></p>
</div>
<?php
}
Code language: PHP (php)
I’ve introduced a namespace called MySimplePlugin
, which you can find right below the plugin heading. This effectively wraps the code in a cocoon, only accessible via the namespace.
From there, I have to modify the way I call the callback function. I renamed the function my_simple_plugin_add_admin_menu
to add_admin_menu
. WordPress filters and actions execute outside of your namespace, so you need to pass in the path (i.e., namespace) to where the function can be found.
// Add the admin menu item.
add_action( 'admin_menu', __NAMESPACE__ . '\add_admin_menu' );
Code language: PHP (php)
This is where PHP magic constant __NAMESPACE__
can be used, which is short for typing out the entire namespace. Another way to write the above would be:
// Add the admin menu item.
add_action( 'admin_menu', '\MySimplePlugin\add_admin_menu' );
Code language: PHP (php)
The “\” characters are called namespace separators. There is a “\” at the beginning to indicate that the namespace is at the root. It works just like regular directories, albeit with a backslash.
Within add_admin_menu
, I add a top-level menu and used the same __NAMESPACE__
trick to reference the callback function render_admin_page
.
// Define the function that adds the admin menu item.
function add_admin_menu() {
add_menu_page(
esc_html__( 'My Simple Plugin', 'my-simple-plugin' ),
esc_html__( 'My Simple Plugin', 'my-simple-plugin' ),
'manage_options',
'my-simple-plugin',
__NAMESPACE__ . '\render_admin_page'
);
}
Code language: PHP (php)
A non-WordPress namespace example
Let’s take a non-WordPress example of namespaces to hammer in some points.
Let’s just create a generic addition function.
<?php
namespace DLXPlugins;
function add( $a, $b ) {
return $a + $b;
}
echo add( 1, 1 ); // 2
die( '' );
Code language: PHP (php)
In this example, I didn’t have to use the fancy __NAMESPACE__
magic constant. I can just call the function add
straight away because the code I’m running is all in the same namespace.
Now let’s see what happens when there are multiple namespaces. What would the following code do?
<?php
// Begin new namespace.
namespace DLXPlugins\Math;
function add( $a, $b ) {
return $a + $b;
}
// Begin new namespace.
namespace DLXPlugins\Homework;
// Try to add.
add( 1, 1 );
Code language: HTML, XML (xml)
The answer is: you would receive a fatal error.
The function add
only exists under the DLXPlugins\Math
namespace. Since add
is being run in the DLXPlugins\Homework
namespace, the function add
doesn’t exist to it.
You could rewrite the above to have it work:
<?php
// Begin new namespace.
namespace DLXPlugins\Math;
function add( $a, $b ) {
return $a + $b;
}
// Begin new namespace.
namespace DLXPlugins\Homework;
// Try to add.
echo \DLXPlugins\Math\add( 1, 1 ); // 2.
die( '' );
Code language: PHP (php)
If you answered, “a fatal error”, you got it exactly right. The second created namespace might as well be on a different planet.
Namespace hierarchy
Let’s use a different example to show namespace hierarchy with three namespaces.
<?php
namespace DLXPlugins\Math;
function add( $a, $b ) {
return $a + $b;
}
// Begin homework namespace.
namespace DLXPlugins\Homework;
function do_homework() {
return \DLXPlugins\Math\add( 2, 4 );
}
function grade_homework( $answer, $addition_one, $addition_two ) {
$correct_answer = \DLXPlugins\Math\add( $addition_one, $addition_two );
if ( $answer === $correct_answer ) {
return 'Correct!';
} else {
return 'Incorrect!';
}
}
namespace DLXPlugins;
$answer = Homework\do_homework();
if ( 'Correct!' === Homework\grade_homework( $answer, 2, 4 ) ) {
echo 'You did amazing!';
}
die( '' );
Code language: PHP (php)
Namespaces flow from the top down, and each bit of code belongs to that namespace until a new one is declared.
The first namespace DLXPlugins\Math
holds the add
function.
Namespace DLXPlugins\Homework
holds functions do_homework
and grade_homework
.
The last namespace is declared as just DLXPlugins
, so we don’t have to prepend anything when calling child namespace functions.
Namespaces and the use
keyword
The previous hierarchy can be polished a bit when it comes to namespaces. Let’s include the add
function without all the messy forward slashes.
This is known as importing a namespace, and we’ll use the use
keyword.
<?php
namespace DLXPlugins\Math;
function add( $a, $b ) {
return $a + $b;
}
// Begin homework namespace.
namespace DLXPlugins\Homework;
use DLXPlugins\Math;
function do_homework() {
return Math\add( 2, 4 );
}
function grade_homework( $answer, $addition_one, $addition_two ) {
$correct_answer = Math\add( $addition_one, $addition_two );
if ( $answer === $correct_answer ) {
return 'Correct!';
} else {
return 'Incorrect!';
}
}
namespace DLXPlugins;
$answer = Homework\do_homework();
if ( 'Correct!' === Homework\grade_homework( $answer, 2, 4 ) ) {
echo 'You did amazing!';
}
die( '' );
Code language: PHP (php)
Now in the homework
namespace, we can just use Math
directly.
Namespaces conclusion
In this tutorial, I went over why namespaces are necessary and how to include them in a basic plugin.
I recommend my tutorial on creating a PSR-4 WordPress plugin for further reading on how to use namespaces in a more complicated plugin.
If you have any questions, please leave a comment below or @me on Twitter. Thank you for reading.
Like this tutorial? There's more like it. Subscribe today!
Ronald Huereca founded DLX Plugins in 2022 with the goal of providing deluxe plugins available for download. Find out more about DLX Plugins, check out some tutorials, and check out our plugins.