Namespaces in WordPress Plugins

Namespaces in WordPress

It’s no secret that many WordPress plugins are poorly designed. Some have been started as simple tools and grew larger until they became unmanageable, others were created by inexperienced developers who did their best. The sad truth is that WordPress provides complete freedom in designing plugins while many developers aren’t ready to take the responsibility. I’ll explain how I design plugins, and the cornerstone of this architecture is utilizing namespaces.

So why do we need namespaces in the first place? The most straightforward answer is shortening names of our classes and functions. Anybody who used to work with Zend Framework v1 (or almost every PHP framework created prior to PHP 5.3) has seen names like this: Zend_View_Helper_Placeholder_Container_Abstract. Imagine every single class name being this long and you get the idea. WordPress plugins often have the same problem – every class, every function you create has to have a unique name among all plugins ever created, so they often end up being too long to be convenient.

However, the most important reason is the logical separation of the code, and it’s particularly noticeable in complex plugins composed of many classes. Namespaces encourage you to build a good architecture by separating classes in logical groups and utilizing design patterns to interconnect them. For example, the Front Controller pattern is famous for its perfect fit into the MVC applications, but it might be just as useful in WordPress plugins.

I assume that you are already familiar with the namespaces syntax, you might want to read the docs first otherwise.

Conventional Way

Let’s say we want to create a simple “Subscribe” plugin. We are going to display the Email field after each post so users could subscribe to our e-letters. “That’s easy!” you say, and write something similar to this:


function gt_subscribe($content) {
    return $content . <<<HTML
    <div>Here comes the subscription form</div>
HTML;
}

add_filter( 'the_content', 'gt_subscribe' );

That is the conventional way, and it works just fine until your plugin becomes too large. Here’s what we are going to do with it:

  • Move the function gt_subscribe() into a separate class
  • Utilize two namespaces: Gt\Subscribe and Gt\Subscribe\Model (GT stands for Geeky Tomato)
  • Logically separate our code into three model classes

You can download source code of the plugin from the GitHub repository.

Models

We are going to logically separate our code into classes to utilize the PHP object-oriented capabilities. For the lack of a better name, we’ll call them models, and you definitely heard that term if you are familiar with MVC. However, the we are not implementing the MVC pattern, so there will be differences.

Here are the classes we’ll need:

  • Model\Display which we use for HTML displaying purposes (it would be a View if we were implementing MVC)
  • Model\Subscribe to handle the subscription process
  • Model\Delivery to send the emails to our subscribers

Display Model

The model contains only one method: form(), which returns HTML code of the subscription form:

<?php

namespace GT\Subscribe\Models;

class Display {

    public static function form( $content ) {
        return $content . <<<HTML
<div>Here comes the subscription form</div>
HTML;
    }

}

As you see, the first line declares the namespace, so we don’t need to worry whether any other plugin contains a class named Display.

Subscribe Model

The Subscribe model is in charge of subscribing a user:

<?php

namespace GT\Subscribe\Models;

class Subscribe {

    public static function handle( $email ) {
        if ( $email ) {
            // insert into the database
        }
    }
}

As you see, the code is pretty simple. The handle() function accepts an email and inserts into the database. For the sake of simplicity the insert DB query itself is omitted, however, it’s perfectly covered in the WordPress Reference.

Delivery Model

Although the Delivery model is slightly more complex, it’s still pretty easy to understand:

<?php

namespace GT\Subscribe\Models;

class Delivery {

    public static function run( $subject, $message ) {
        $emails = self::_get_emails();
        foreach ( $emails as $email ) {
            self::_send( $email, $subject, $message );
        }
    }

    private static function _get_emails() {
        // load the emails from the database
        return $emails;
    }

    private static function _send( $email, $subject, $message ) {
        return mail( $email, $subject, $message );
    }

}

You might ask why everything is static. That’s the limitation of the callbacks I’ll explain below, however, fits our design quite well.

It’s Alive!

Finally, it’s time to make our models work, so how do we do that? WordPress is a powerful framework, so we will utilize actions and filters it provides.

First, we define the namespace and include the models:


namespace GT\Subscribe;

use GT\Subscribe\Models;

include 'models/display.php';
include 'models/subscribe.php';
include 'models/delivery.php';

Then comes the Display model. We will display the form at the end of each post, so we are going to go with the the_content filter:

add_filter( 'the_content', [ 'GT\Subscribe\Models\Display', 'form' ] );

You might wonder why we need to provide the full namespace if we already define the namespace with the use statement. At the time the callback is actually called by WordPress PHP has no idea of the namespaces that were in use when you added it.
Another way to solve this is to instance the class before passing it into the callback:

$display = new Models\Display();
add_filter( 'the_content', [ $display, 'form' ] );

We won’t do that for one simple reason – the class will be instanced each time the code is performed, which is basically each time the website is opened. In our case it is insignificant, but still not a good practice, so we will avoid it. Therefore, we need to keep methods of our model static so the could be called without creating an instance of the class.

We will discuss the issue in the next article.

Next, let’s handle the subscription process:

add_action( 'init', function() {
    if ( ! empty( $_POST['gt_subscribe_email'] ) ) {
        Models\Subscribe::handle( $_POST['gt_subscribe_email'] );
    }
} );

And finally we send out emails:

add_action( 'publish_post', function( $ID, $post ) {
    Models\Delivery::run( $post->post_title, $post->post_content );
} );

Every time a post is published, we send it to the subscribers.

What’s Next?

The plugin structure is incomplete without the request handler, and that’s what we are going to cover in the next article. We will use the Front Controller design pattern to handle HTTP requests and interact with WordPress.

Stay tuned!

Leave a Comment

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.