Menu

Permanent Tourist

A personal website by Mark Howells-Mead

An easy introduction to WordPress plugins with PHP classes

There are many copy-and-paste examples of how to write your own functions and apply them through WordPress’ hooks and actions. But with a little simple knowledge of PHP’s namespace syntax, developers who regularly work on WordPress projects can make their lives a lot easier, whilst making their code much more robust, portable and secure.

The first thing to recognize is whether the modification you’re applying is a one-off. Is the function specifically tied to a particular design? Is it required no matter what the site looks like? Is the functionality directly relevant to the Theme you’re working on, or is it an independent functionality, which needs to apply whichever Theme is being used?

If the functionality has no direct correlation to the Theme, then it belongs in a plugin, not the functions.php file for the Theme.

Naming conventions

A WordPress plugin is best created by making a subfolder with a unique name in the /wp-content/plugins/ folder. You can just create a single PHP file in the /wp-content/plugins/ folder, but that’s a bad idea because you will often need to store JavaScript, CSS or translation files with the plugin code.

It’s advisable to use your own prefix for plugins you make yourself – in my case, mhm- or permanenttourist-, or frp- for work projects. In that folder, you need a single PHP file, which contains the code for your plugin. How you name the file is up to you, but if you change the folder name once the plugin is active, then you’ll need to re-activate the plugin. In this example, we’ll use the plugin name mhm-great-plugin.

(Don’t forget to add the required header to the content of the plugin’s main PHP file, so that you can activate the plugin in WordPress’ admin area.)

PSR is a good standard for PHP coding, which will make it a great deal easier to fix bugs as they occur, and to ensure a common standard across all of the code you work with. Many editors – like Sublime Text – can use PSR validation through the use of editor plugins.

One example of PSR is that every PHP class is alone in its own file, and that the file name should correspond with the class name. So a class called Plugin belongs in a file called Plugin.php and a class called PluginOptions belongs in a file called PluginOptions.php.

Using PHP classes

PHP classes are used to group functionality into one “object”. By grouping functionality together, you can easily avoid naming conflicts – a function called sendEmail()  is too ubiquitous by far. But if you put that function into a PHP class, you won’t run into such problems.

Many examples of code “snippets” for WordPress without PHP classes recommend using a convoluted prefix for every function name to get around naming conflicts. For example mhmgreatplugin_sendEmail(). This advice is mainly given so that beginners don’t have to get their heads around PHP classes. If you’re serious about making a robust plugin, then it’s important to get the quite simple principle of PHP classes under your belt.

If you have a plugin containing a few functions, then using individual functions with prefixes means that you’ll have to pass data between them using function arguments. That works, of course, but if you’re passing data through half a dozen or more different functions, you’ll quickly get lost if the end result isn’t as you’d expected.

Making a class is easy. Here’s an example.

<?php
class Plugin {
  public function sendEmail(){
    wp_mail(……………);
  }
}

The functions in a WordPress plugin class are usually prefixed with the definition public so that other scripts – like the ones in WordPress core – can access them. If you prefix them with private or protected, then WordPress Core can’t use them. Private functions are certainly allowed, but only if they’re accessed directly from another function in your Plugin class.

Using namespaces

PHP Namespaces are used to group individual classes together so that class naming conflicts don’t occur. WordPress is built so that it works using PHP 5.2, which doesn’t support namespaces. But that doesn’t mean that you can’t use them yourself. Just make sure that you add a PHP version check before trying to use your code in a WordPress website.

When you look at the example above, you’ll see that the class name Plugin is very ubiquitous. To get around conflicts with other classes called Plugin, you can define a namespace to which the class belongs. For WordPress plugins, the easiest way to do this is by using the name of the plugin as the namespace.

A namespace definition at the top of the PHP file means that every reference to a class name in the current file belongs to the namespace MhmGreatPlugin. This means that your class Plugin now actually means MhmGreatPlugin\Plugin. The namespace should correspond to the plugin name, but using PascalCase format. (Capitalize the letter after each dash, then remove the dashes.)

<?php
namespace MhmGreatPlugin;
class Plugin {
  public function sendEmail(){
    wp_mail(……………);
  }
}

You can also go a step further and use nested namespaces: for example Mhm\GreatPlugin. This will mean that you can group all of the plugins you write under your common “main” namespace Mhm. This will help you to organize your code more logically if you need to interact between your plugins or classes.

If you need to refer to a class in another namespace, then you’ll need to do one of the following.

  • Reference the other namespace and class at the top of your PHP file: use TheOtherNamespace\ClassName; so that you can use ClassName in your code without the namespace prefix.
  • If the class in the other namespace is also called Plugin then you’ll need to use TheOtherNamespace\Plugin as TheOtherPlugin;. and then new TheOtherPlugin(); when applicable.
  • Always fully-qualify the namespace and class in your code: $other_class = new \TheOtherNamespace\ClassName();
  • If the other class is not in a namespace, then prefix the call to it with a backslash: e.g. $iterator = new \RecursiveDirectoryIterator().

So now we have a class defined, with a function ready for our PHP code. That functionality is up to you, of course! But nothing will happen yet: all we’ve done is define the class and its functions.

Instantiate the class

Imagine you’ve built a set of rules for how an engine works and now you want to start a new engine running. To do that, you need to make a new engine built on the rules and functions you’ve written. In this case, the “engine” is the plugin.

<?php
namespace Mhm\GreatPlugin;
class Plugin {
  public function sendEmail(){
    wp_mail(……………);
  }
}

new Plugin();

As long as the new Plugin() call is in the same file (or in the same namespace) as the class itself, don’t specify the namespace explicitly as part of the call. That means you can have several plugins running at the same time, each of which based on a class called Plugin, as long as each of them is in a different namespace.

This code will still not send the mail, because you haven’t called the function sendEmail yet. This can happen whenever is applicable for your plugin, but for the sake of ease, we’ll send an email whenever you instantiate this class. There are two ways to do this.

We could assign the new instantiated object to a variable, then run the function sendEmail() by calling the following code.

$mhm_great_plugin = new Plugin();
$mhm_great_plugin->sendEmail();

That works fine, but it’s better to try and keep all of the functionality within the class, thereby avoiding the need for the complex (and otherwise unnecessary) variable name $mhm_great_plugin.

We will also encounter the problem that we don’t want to call the sendEmail function immediately, but when a WordPress hook or action trigger is fired.

The special function __construct in a class is run automatically whenever you instantiate the class, so we can run the sendEmail function from within the constructor function.

<?php
namespace Mhm\GreatPlugin;
class Plugin {
  public function __construct(){
    $this->sendEmail();
  }
  public function sendEmail(){
    wp_mail(……………);
  }
}

new Plugin();

As you can see, we use $this within the class to refer to the instance of the class we’ve created.

Attaching a class function to a WordPress hook or action

The second parameter of the WordPress functions add_filter and add_action most commonly take a function name as a string in online examples. But you can also pass an array as the second parameter: the first array attribute being the class instance and the second attribute being the name of the function within the class as a string.

If we want to send the email when the admin hook admin_init is run, then we can modify the class. By adding our function to the admin_init hook, we can make sure that the email is dispatched at the appropriate moment.

<?php
namespace Mhm\GreatPlugin;
class Plugin {
  public function __construct(){
    add_action( 'admin_init', array( $this, 'sendEmail' ) );
  }
  public function sendEmail(){
    wp_mail(……………);
  }
}

new Plugin();

In upcoming blog posts, I’ll go into more detail about how we can use a second class in our plugin to easily define some plugin options, and how we can add our own hooks to modify the output of an HTML-generating function.