Namespaces in WordPress Plugins: What They Are and Why They Are Useful

Illustration of multiple satellites in orbit around Earth, surrounded by an expanse of space debris, depicting a crowded low earth orbit.

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

A photo of four satellites orbiting closely together over Earth
Collisions Occur When Two Objects Occupy the Same Space and Time

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.

( ! ) Fatal error: Cannot redeclare get_field() (previously declared in /Users/ronaldhuereca/Sites/localhost/beaverbuilder/wp-content/mu-plugins/dlx-namespace-example.php:13) in /Users/ronaldhuereca/Sites/localhost/beaverbuilder/wp-content/plugins/advanced-custom-fields/includes/api/api-template.php on line 20
Fatal Error From Having Two Functions With the Same Name

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)
Sample Admin Page Example Output
Sample Admin Page Example Output

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.

Ronald Huereca
By: Ronald Huereca
Published On: on April 28, 2024

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.

2 thoughts on “Namespaces in WordPress Plugins: What They Are and Why They Are Useful”

Leave Your Valuable Feedback

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

Shopping Cart
  • Your cart is empty.
Scroll to Top