I’ve been developing WordPress plugins and themes for quite some time now. From my own website to the websites I develop at work, I’ve got a fair amount of WordPress development time under my belt. I’ve also learned a LOT since the first line of WordPress related code that I wrote. I finally feel like I’ve brought my WordPress development into a more modern era.
The biggest issue that I’ve had with WordPress development since I started is that themes and plugins are mostly made up of random functions in a single file. That can get really messy REALLY quickly. Sure … WordPress itself has been moving to more modern development practices (i.e. object oriented programming) in recent years, but there are still a lot of themes and plugins out there doing the “random functions in a file” thing.
I had already started creating classes to encapsulate functionality, in both my theme and my plugin development. But I found myself forgetting to include new classes in the main plugin file so that WordPress knew about them and thus blowing things up. Oops. So the main thing that I wanted to bring into my WordPress development routine was autoloading.
I have also gotten used to using namespacing after working with the Laravel framework and with Composer over the past couple of years. Namespacing isn’t something that I see much in WordPress, but it just feels natural to me.
My first attempt at bringing both namespacing and autoloading into my WordPress development routine involved using Composer. But using Composer simply to set up the autoloading (and not pull in any packages) was kind of silly (and overkill). So I did some more research (and ended up on StackOverflow a LOT) and figured out a better (more simple) way to be able to bring both into my WordPress development. I’m not saying that this is the best way to do things, but it has been working for me for the past few months. I wanted to share in the hopes that it might help someone else out.
The first thing that I did was change up the file structure for my plugins. Instead of throwing all of the files into the plugin directory, I started grouping things in a similar way to how I have grouped files in the packages that I’ve developed for my Laravel CMS. Here’s an example for a fake plugin called Foobar. Foobar is a very simple plugin that creates a custom post type (foobar) and a custom taxonomy (foobar-group).
The src folder contains the bulk of the functionality for the plugin. For a simple plugin or a plugin that only creates a custom post type, I tend to include everything in the Core.php file. For more complex plugins, like those that include custom taxonomies, I create a file for each taxonomy that contains the functions related to registering, managing, and displaying the taxonomy (Groups.php in the above file structure).
Now that I have all of my files set up, I need to make sure WordPress knows where to find them. I decided on the following for the autoloading functionality. I put this function in the main plugin file (i.e. foobar.php).
* Register the autoload functionality for the plugin.
// trim off any opening slashes
$class_name = ltrim($class_name, '\\');
// if this isn't for our plugin, do nothing
if(strpos($class_name, 'BECKY\Foobar') !== 0)
// determine the file to load
// - strip off the plugin namespace to get just the filename
// - classes are in the 'src' directory
$class_directory = realpath(plugin_dir_path(__FILE__)).DIRECTORY_SEPARATOR.'src'.DIRECTORY_SEPARATOR;
$class_name = str_replace('BECKY\Foobar\\', '', $class_name);
$class_file = str_replace('\\', DIRECTORY_SEPARATOR, $class_name).'.php';
$path = $class_directory.$class_file;
// make sure the file exists
The BECKY\Foobar in the function is the namespace base for this plugin. Foobar because that is the name of the plugin. BECKY is the “client code” in this example. You see, at work we have 5 character codes for each of our clients. I use that client code as the namespace base for the plugins that I develop for the projects.
The last thing that I have to do is get the core functionality for my plugin all set up. I don’t have to include the individual class files anymore. WordPress already knows where to find them because of the above autoloading functionality.
I include a function similar to the following example in the main file of my plugin to get the plugin going.
* Gets the plugin going.
$core = new BECKY\Foobar\Core();
I can now use namespacing in all of the classes that I need to implement the functionality needed by the plugin and WordPress will know where to look for those files.
That’s it. Easy peasy. 🙂