PHP namespaces are a great way to escape any errors that are triggered due to having more than 1 function or class with the same name. In this tutorial, I will show you how to use PHP namespaces in WordPress Plugins.

PHP Namespaces Basics

Before we go into using them in WordPress plugins, I want to tell you about the basics of them. If you’re familiar with them already, you might want to skip this and move to the next section.

There is more to learn about namespaces than what I will tell you here, but this will be just essentials so you can follow my tutorial. If you want to learn everything about PHP namespaces, you can learn it here.

When coding with namespaces, just picture them in your mind as if you are working with folders or categories. Each namespace is a folder, each sub-namespace is another folder inside that one.

Define them on each file on the first lines

That is the first rule that you need to know. If you try to process any class, function or even HTML before the defined namespace, you will get an error.

<?php
/**
* This is a comment on the file to define what is it about.
* This comment can be before or after the namespace.
*/
namespace My_Plugin;

With this definition, every function or class that is defined in this file will be considered as part of the namespace My_Plugin.

Calling Functions or Classes

When you want to process a function or instantiate a class, you need to be aware of the namespaces. If a function is called in a file that is also under the same namespace, you can call it directly.

<?php
namespace My_Plugin;

/**
* We have a function inside another file that is also under same namespace.
*/
$users = get_users(); // This function is define in another file under namespace My_Plugin.

Calling external Functions or Classes

If we want to call functions or classes that are outside of our namespace. For example, let’s say we will use the WordPress function wp_insert_post(). How can we call that under our namespace?

<?php
namespace My_Plugin;

// This is fine if we don't have a function with the same name under our namespace.
$post_id = wp_insert_post(); 

// This is fine since we are telling to look at the global space.
$post_id = \wp_insert_post();

What if we have to call external functions that are also inside their own namespaces? That is almost the same.

<?php
namespace My_Plugin;

$external_namespaces_function = \Some_Namespace\function_name();

But, again, what if you want to call that function several times in the same file? Typing all that is a bit cumbersome. You can define that you will use that function at the beginning of the file.

<?php
namespace My_Plugin;
// If you are importing a class, you don't have to type "use class", just "use".
use function Some_Namespace\function_name;

// Now I can use that function directly
$external_namespaces_function = function_name();

What if you have your own function with the same name under the current namespace? You have several approaches.

Approach #1: Just importing the function

<?php
namespace My_Plugin;
use function Some_Namespace\function_name;

// Now I can use that function directly
$external_namespaces_function = function_name();
// But I want to call my own function with the same name!
$my_function = namespace\function_name();

Approach #2: Using aliases

<?php
namespace My_Plugin;
use function Some_Namespace\function_name as otherfunc;

// Now I can use that function directly
$external_namespaces_function = otherfunc();
// Our own function.
$my_function = function_name();

Approach #3: Importing the namespace

This is useful if you have external (or yours) sub-namespaces.

<?php
namespace My_Plugin;
use Some_Namespace\functions;

// Now I can use that function.
$external_namespaces_function = functions\function_name();
// Our own function.
$my_function = function_name();

PHP Namespaces in WordPress Plugins

Such namespaces can be also used in themes of course, but as I focus more on WordPress Plugins, I will talk about that.

For this tutorial, I will have a simple plugin with dummy functions. Those functions will be used to retrieve users from DB or from an API. I will use the same function name get_users() for both and the namespace will define how the function will retrieve and process the data.

Main File

Create a folder for your plugin and then place the next code in the main file of that plugin. It can just be something like test-plugin/test-plugin.php if you want.

Once you’ve done that, go to the Plugins menu and activate the plugin. If the plugin is activated, you can then easily see if there are any errors. At the beginning of the file, we have defined a namespace My_Plugin. That means that everything in this file will be considered to be under that namespace.

Folders and Files

Let’s also create the necessary folders and files for this tutorial. As I’ve said before, if we are to think of namespaces as folders, we can also create such folders and organize our code even better.

Since we will have two more namespaces, for database and API functions or classes, we will have two folders db and api. Put those folders under the folder includes. After that, create a file inside the folder db and name it functions.php.

Do the same inside the folder api and also create another file in there. Name it class-api.php. We will now extend our main class and include all that.

Load our Plugin in a hook

Most of the content is just a showcase of classic usage of PHP namespaces, but this part is a specific one. This one will really show you how to use PHP namespaces in WordPress Plugins. Why? Because we will use WordPress hooks here and.

We will load our plugin inside the action hook plugins_loaded.

If you look closely, we are passing our function name together with the namespace under which the function my_plugin_load is defined.

In older PHP, we might had to call the add_action as \add_action since that function is in global space, but in newer PHP, if there is no definition of that function, it will look at the global space for it. If I am wrong here, please correct me in the comments below.

Database Functions

We have loaded our plugin, everything is ready. We need to define our database function that can retrieve the users from the database. Since this is just a showcase of using namespaces, that function is a dummy one. Open includes/db/functions.php and add this code:

So, what have we done here?

  • Defined a DB sub-namespace under My_Plugin
  • Defined a function to retrieve the users from database.

If we are to call that function outside of DB, we would need to call it like \My_Plugin\DB\get_users() or if we are under My_Plugin namespace, then we can call it like DB\get_users(). Neat, right? 🙂

API Functions & Class

Open includes/api/functions.php and add this code:

Pretty straightforward. It is the same as what we have done for the database functions. We now have the same function name get_users() but the logic inside that function is different. We are also instantiating an object from API class.

Since this class will be defined under the same namespace My_Plugin\API, we can call it directly here. Let’s define it now. Open the file includes/api/class-api.php and add the next code.

Again, this is just a dummy class to show how we could retrieve the users from an API. We are calling directly the WordPress functions because PHP will check the global space for them.

Getting the Users

Those functions are not used at all, anywhere in our code. To see the benefit of defining functions under namespaces, I want to show you a way to get those users from our main file. We will define a method for that. Add the next code to our main class.

We have a helper method use_api(). This method could define if we are to retrieve the users from the database or the API.

Another neat thing here is that we don’t have to define the usage of functions from the sub-namespaces. We can call them directly by specifying the sub-namespace. That is what we have done by calling them with DB\get_users() and API\get_users().

Saving the Users from API in Database

What if we want to save all the users from the API inside our database? That is a possible scenario in some solutions. We will define such function inside the DB sub-namespace because we might have to use several database functions (in a real solution).

That might raise an issue if we don’t know how to call the API functions from the other namespaces and sub-namespaces. But we now know that and let’s see how to do that.

We will use the class API from our API sub-namespace, so let’s define that we will use that class at the beginning of includes/db/functions.php.

Here is now an example on how to call that API:

Conclusion

PHP Namespaces in WordPress plugins can help you even with the organization with folders and files. By forcing yourself into using them more, you will force yourself to organize the code and maybe even make the whole architecture of your solution much better.

Even I have yet to start using them more. I plan to refactor all my plugins with namespaces and thus making the code more maintainable.

If you wish to get the whole code in the form of the plugin, I have a file here.

This part is available only to the members. If you want to become a member and support my work go to this link and subscribe: Become a Member

Become a Sponsor

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.

11 Comments

  1. Hi,

    Thanks for your wonder full post for a oop technique in wordpress plugin

    could you please help me to solve the issue of including php file does not exist properly on my end using class method.

    Reply

  2. Hi,

    here i have added my code

    init_hooks();

    }

    private function init_hooks() {
    add_action( ‘plugins_loaded’, array( $this, ‘themeslug_custom_features_includes’ ), 11 );
    }

    /**
    * Include required core files used in admin and on the frontend.
    */
    public function themeslug_custom_features_includes() {

    require_once( plugin_dir_path( __FILE__ ) . ‘includes/theme-slug-custom-user-profile.php’ );

    require_once( plugin_dir_path( __FILE__ ) . ‘includes/theme-slug-custom-metabox.php’ );

    require_once( plugin_dir_path( __FILE__ ) . ‘includes/theme-slug-optinbox-widget.php’ );

    require_once( plugin_dir_path( __FILE__ ) . ‘includes/theme-slug-recentpopularpost-widget.php’ );

    require_once( plugin_dir_path( __FILE__ ) . ‘includes/theme-slug-socialfollow-widget.php’ );

    require_once( plugin_dir_path( __FILE__ ) . ‘includes/theme-slug-sticky-widget.php’ );

    }
    }

    Reply

    1. Hi, I am not sure where your code is placed, but try displaying the plugin_dir_path( __FILE__ ) and see what you get there. If that is a code in a theme, you can’t use the plugin_dir_path. If that file is not the base plugin file, you will have to use a different way of referring your path to the includes. Also, is init_hooks called with $this->init_hooks()?

      Reply

  3. HI, WHen i call function is_edit_page() of wordpress, but it show “Fatal error: Call to undefined function”.
    So, how i do for call this function.
    thanks you

    Reply

    1. Hi, I am not sure this function exists in WordPress.

      Reply

  4. Finally got a nice place to understand php namespaces; explained really nicely. Thanks 🙂

    Reply

  5. why not use psr autoloading …?

    Reply

  6. Thank you for this guide! I was struggling to wrap my head around calling wordpress functions from the global scope after I have defined my own namespaces and now my code is running as desired.

    Reply

  7. What do you think about the Name Conventions of WordPress? If use names like a class-my-plugin.php according to this convention it won’t work with PSR-4. How you solve this?

    Reply

    1. Hi, it won’t work with PSR-4, that’s correct. You could create a custom autoloader for such classes. You can check this tutorial on that: https://code.tutsplus.com/tutorials/using-namespaces-and-autoloading-in-wordpress-plugins-4–cms-27342

      Reply

  8. Thanks! Very clean example of using Namespaces in WP!

    Reply

Leave a reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.