WordPress plugins – reStructure

By using a unified naming convention you know where the class you need is declared, to be able to load it into your code. The mind forgets easy, and you want to focus on solving your programmatical problems instead of trying to remember where you put your six weeks old myURLHelper class.

This is a follow up on my last post about the directory structure of WordPress plugins. Previously I grouped the PHP files in directories based on functionality, such as “admin”, “js” and “widget”. Now it’s time to refactor this. This does not apply only to WordPress plugins, but to all software development.

When using a programming language, it’s not a bad idea to follow some of the best practices that already exists. PEAR is a large PHP project repository. Most of the up-to-date packages there follow strict directory and file structures along with a set of coding standards. The classes use namespace alike names where each nested namespace is separated with an underscore. These classes are then placed in files named after the last part of the class name, in a directory hierarchy where each directory is named after each part of the namespace.

As an example, the class “Datafeel_Util_URL” is defined in the file “URL.php” under the directories “Datafeel/Util”.

If you have multiple projects that requires the same functionality, you keep all your files and directories under a single path, which you add to the PHP include path configuration parameter. If you create a PEAR package of your project, you can install it globally on your system, and PHP will most likely be able to find your files without changing the include path. Please note that setting up and creating PEAR packages can take some time if you haven’t done it before. Unless you have special needs, such as releasing the project on PEAR, you can happily change the include path and you are good to go.

I have been working on functionality for two WordPress sites lately, and those two sites require some of the same functionality. I started out by just copying the code from the first project to the second, but then all the hard work begins. I decide to rewrite the configuration handler, then add a new web service and fix some bugs related to file uploads. I think it’s hard to keep the plugins from the two projects in sync. Imagine if I had three projects, or ten…

WordPress plugins – Directory Structure

When you develop a plugin for WordPress that continuously grows with new functionality it can become very large with an unmanageable amount of files in the plugin directory. The files can grow that large that it becomes almost impossible to understand the flow and integrity of the code. This will also affect the gain of WordPress. One example is the plugin administration page that searches through all PHP files in all the subdirectories one level below the plugin directory for files with a valid plugin header.

This document contains some thoughts about a well structured plugin directory to speed up you plugin and keep the code for all the functionality in a maintainable structure.

If you only store one PHP file in the main directory of you plugin, a file we can call the “loader”, we might increase the gain a little. The only task of this file is to load the rest of the files in the plugin. This loader will load a controller that we name the “core”. The controllers tasks are, among others, to set up action and filter hooks to integrate into WordPress and other plugins and to control the flow of data inside the plugin.

The most important reason to arrange the files is to get a better overview. One way to do this is to make use of subdirectories based on functionality and file types. You could place all your Javascript files inside a “js” directory and your CSS files inside a “css” directory. If your plugin has a administration interface those files could be placed in a directory called “admin”, likewise could widget related files be located inside a “widget” directory. Keeping a structure like this demands a little extra code and will give you more files to keep in mind, but in return you’ll never see your files grow into huge monsters of several thousands lines. Files growing out of control can easily become a problem, which I have experienced myself when developing WordPress plugins.

An example with a directory structure for a plugin of a pretty large size:

my_plugin_loader.php
/actions/controller.php
/actions/widget.ajax.php
/admin/options.php
/core/my_plugin.php
/css/admin.options.css
/css/widget-css.php
/js/script-loader.php
/js/some_lib.js
/js/widget-js.php
/languages/my_plugin-nb_NO.po
/languages/my_plugin-nb_NO.mo
/widget/widget.control.php
/widget/widget.php

I have used some suitable file names. It is not necessary to specify the directory name as a part of the file name, as I have done for some of the files above, but you might want it if your editor only shows you the name of the file. I use Eclipse for development which only shows me the name of the file. That makes it harder to separate different files with the same name from each other.

In my example I have a file named “script-loader.php” which is used to load Javascript files. WordPress contains functionality to register scripts with a name, URL and dependencies. It is also possible to specify the version of the script, which becomes a part of the URL. This is useful to force browsers to downlad the new script file instead of using a cached one.

You might want to make directly calls on functionality in your plugin, not from a file in another plugin or a file in the selected theme, but maybe to load some data with a Javascript, execute an update or print a CSS or Javascript file requested by the browser. You need a front controller to handle these requests.

I use PHP5 and an object oriented structure when I develop plugins for WordPress, but the thoughts and suggestions in this article might be used perfectly with a structural, non object oriented, methodology. There are many pourly written plugins for WordPress, hacked together to give only the functionality needed at the given time. This makes it harder to maintain the plugin later when new requires show up and makes the integration with other plugins or newer versions of WordPress to a nighmare. Those plugins are then used as a base for other peoples plugins with the famous copy and paste method. I believe that better documentation with good examples can increase the code quality for plugins.

This is a translation of my norwegian blog post.