One thing I have been experimenting with recently is adding namespacing and autoloaders to new WordPress plugins.
What Are PHP Namespaces
PHP namespaces was introduced in version 5.3. Namespaces is a way of grouping classes together into virtual directories, the main reason we would want to do this is to help avoid collision of class names in your application. In PHP you can not define two classes with the same name, if you do this PHP will display a fatal error in your application. Using namespaces means that you can define two classes with the same name as long as they are in different namespaces. For example if you had two classes both named Table and both classes perform different tasks, one will be used to read a database table and the other will be used to display a HTML table. If these are not in namespaces then PHP will throw a class is already defined error, the old way of fixing this problem would be to prefix the class name with something unique.
Using Namespaces
In other PHP frameworks such as Zend and Symfony they are built to support the newest versions of PHP and therefore use features such as Namespacing, also because of using namespacing they can also use autoloaders to include the different classes needed in the application. But WordPress wants to be backward compatible with PHP version 5.2, as namespacing was included in 5.3 they don't use PHP namespacing in the core or and they do not recommend using it in your plugins or themes. With the advantages you get from using namespacing and autoloaders in other PHP development I feel it's time to move this over to WordPress development. I feel it's important for servers to stay up to date with the latest versions of languages that websites are built on. I know in most cases it's difficult for websites to always keep up to date with the latest versions which is why WordPress tries to be backward compatible with 5.2 but at the time of writing this PHP closed support with version 5.2 4 years ago on 6th Jan 2011. You can see unsupported dates on this table. Unsupported PHP Versions Looking at this table you can see that even 5.3 is not supported anymore as of 14th Aug 2014 as 5.3 was released on 30th June 2009, so it's coming up to being 6 years old...it's time to move on.
Using Namespaces In PHP
If you haven't used namespaces in development or in PHP before, I've wrote a previous article about how you can get started with namespacing in PHP. Namespaces With PHP Development
Using Namespacing In WordPress
We are going to look into how you can add this into our WordPress plugins. As WordPress doesn't support namespacing or autoloading then we will need to define our own autoloaders when starting a new plugin. The first thing we are going to need to do is create our plugin's first file, this is the file WordPress will load when running your plugin code. To do this create a file at the root of your plugin and include the plugin header comments.
/**
* Plugin Name:
* Plugin URI:
* Description:
* Version:
* Author:
* Author URI:
* Text Domain:
* License:
* License URI:
* Domain Path:
*/
Next we need to create our own autoloading functions so that the other files in the plugin can simply use this autoloading function. You can either directly add this code to this first file but I would suggest moving this into it's own file. This should be the only time in your plugin you will need to use a require_once to load PHP code.
require_once 'autoloader.php';
Now in our autoloader file we can create the autoload function, if you are new autoload functions you can learn more about registering your own autoload functions in one of my previous articles. To register your own autoload function you need to use the function spl_autoload_register('autoload_function').
spl_autoload_register('autoload_function')
The way that this function works will all depend on the coding standards you are using in your WordPress plugin. In this example we will work off the standard WordPress coding standards i.e filenames are in lowercase with words separated by dashes, with class names defined as first letter uppercase and with underscores. Because of how the class names are defined with uppercase first letter and underscores, this is how we will define our namespaces. Therefore if we would have an admin class that we want namespace at the top of the class we will define it like this.
namespace Plugin_Name\Admin;
class Admin
{
}
If we then have a class that defines the settings page for the admin area, we could create a class to handle the creation, this will be in a folder inside the admin folder of the plugin and therefore define the class as.
- plugin-name
- admin
- settings
- settings-page.php
- settings
- admin
namespace Plugin_Name\Admin\Settings;
class Settings_Page
{
}
If we want to call this settings page from the admin class we would normally have to add a require_once to first include the file before we can use the class, but as we have an autoload function we simply just need to call the class.
namespace Plugin_Name\Admin;
use Plugin_Name\Admin\Settings\Settings_Page;
class Admin
{
public function __construct()
{
$settingsPage = new Settings_Page();
}
}
Now we know how the namespacing and class names are defined we can go back and create the autoload function.
function autoload_function( $classname )
{
$class = str_replace( '\\', DIRECTORY_SEPARATOR, str_replace( '_', '-', strtolower($classname) ) )
// create the actual filepath
$filePath = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $class . '.php';
// check if the file exists
if(file_exists($filePath))
{
// require once on the file
require_once $filePath;
}
}
Let's investigate how this works, when PHP can not find a class in the loaded files it will search through any registered autoloader functions and run the code in these passing in the fully qualified class name, which as we have defined the namespacing the same format as the file structure we can use this to find our file.
- Explode the class path so we have an array of the path.
- array_map each element of the array to change the name to lowercase and change any underscores to dashes.
- Define the full file path using the WordPress constant WP_PLUGIN_DIR, PHP constant DIRECTORY_SEPARATOR then implode the array using DIRECTORY_SEPARATOR, then add the .php extension as we are going to use this for classes.
- Check if the file we're searching for exists using file_exists().
- If the file exists then use require once to include the file in the application.
This is how you can use namespacing and autoloading in your WordPress plugins.