Say that you’re working on a project for someone and you’ve scoped it out, tasks are delegated, you have all the libraries and tools you need to get started, and you’ve separated what will be the theme or presentation, and what will be the functionality or the plugins.

But rather than having a handful of individual plugins, what if there was a package of smaller functional plugins or micro-plugins or whatever you want to call them working to power the package?

PSR-4 Autoloading WordPress Plugins: Example Organization

Furthermore, these all of which are built on the same foundation but that also share code with one another and to make things more interesting, you opt to use a PSR-4 autoloader via Composer to take care of all of this?

PSR-4 Autoloading WordPress Plugins

First, the way to think about what I’m trying to say (because who knows if I’m clear 🙃)  is that you’ve got your work in the wp-content/plugins directory. And your plugin resides in, say, acme-plugins and has subdirectories for your micro-plugins.

We’ll keep this simple for this example and say there’s the main plugin and then only one micro-plugin. The directory would look something like this;

PSR-4 Autoloading WordPress Plugins: Directory Structure

Now, there’s the files you’ expect to see in a plugin:

  • README,
  • LICENSE,
  • CHANGELOG,
  • composer.json
  • composer.lock
  • vendor
  • the plugin bootstrap file,
  • etc.

Now here’s the thing: If you’re using PSR-2 and you’re going to be using a PSR-4 autoloader, then there are two things that you need to know:

  1. The namespaces should match the directory organization. I talked a bit about this during my WordCamp Atlanta 2017 presentation (specifically under virtual and logical organization).
  2. How to work with composer.json to define your autoloaders. You can read a lot about this here, but I’ll give the cliff notes in the remainder of this post.

So the problem is that the vendor directory resides a level above where some of the source files exist. Thus, the standard way of setting up a custom autoloader in Composer won’t work.

For example, it’s very typical to see this:

But to compensate for our work, we need to do this:

It’s a simple change, but it’s a simple example, right? So what’s the takeaway from this?

Note that we’ve updated some changes in the autoload location. Specifically, this is what’s going on:

  • The first item is the top-level namespace to which all plugins that will belong to the Acme Plugin will belong.
  • The second entry refers to the MicroPlugin that you see in the directory shot above. This represents the namespace for this particular plugin, and it tells Composer to look for source files to autoload using the property directory

From here, you will add a new entry for the autoloader that correspondings to each micro-plugin that will belong to the top-level plugin.

Organizing Future Micro Plugins

There are a few ways that you can handle organizing your code so that you can use a default autoloader.

If you follow the micro-plugin (for lack of a better term) model, then it won’t work so you’re left with having to re-organize your files, and that can be a pain over time.