WordPress plugin design is not something that we often read about explicitly, is it? Instead, we often talk about functionality, performance, and things like that (not that they are unimportant, but they are just one part of the conversation).

When it comes to WordPress plugins, the functionality one offers may range from very small to incredibly large. And this is how it is with almost any type of product, isn’t it?

WordPress Plugin Design: WordPress Plugins

“Plugins extend and expand the functionality of WordPress. 46,537 plugins with 1,392,817,734 total downloads are at your fingertips.”

Sometimes, I think we have a tendency to want to say “focused, and lean” with smaller plugins as if a larger plugin can be described as such simply because of its nature.

But that’s not true.

There are very small, well-built plugins that offer one or two features. And there are large plugins that are also well-built that offer a plethora of features. On the flip side, either type may also be unfocused, cobbled together, and may be anything but what we’d like it to be.

When you look at the landscape of all that’s offered regarding WordPress plugins, it raises a few questions (at least from a developer’s perspective).

I’m going to cover them all in this post, too! Or not.

But seriously, one of the things I’ve been thinking about is this:

At what point do you begin organizing your code, so it includes namespaces, autoloading, dependency management, and other such features that take it beyond a collection of classes or functions?

This implies a lot about a given hosting environment and a developer’s level of familiarity with PHP and experience with other tools, but that’s secondary to the question (and I’ll cover all of that momentarily).

WordPress Plugin Design

According to the requirements page on WordPress.org, they recommend at least the following:

Features such as namespaces and autoloading have been available in versions of PHP prior to 5.6, and dependency management can be handled with tools such as Composer.

So arguments against using any of those three things aren’t something I’d entertain as part of this post. And yes, there are more advanced things we can do with newer versions of PHP. But, all the same, they aren’t things I’d entertain for the point of this post.

Namespaces

Though they aren’t required, I find using namespaces helpful when working with object-oriented code. I try to make sure my namespaces (which can form a virtual path to a class) mimic the directory structure (or the physical path) to a class.

WordPress Plugin Design: Namespaces

I don’t know if this is the prevailing strategy or not, but it’s what works best for how I conceptualize the organization of my code.

Are namespaces something we should bother introducing in smaller plugins?

Though some arguments against using them can be made, I tend to favor using them (though this hasn’t always been the case). No, I’m no fan of the whole architecture astronaut mentality, and I try to be as pragmatic as I can when creating solutions for others – be it for fun or profit.

But if there’s one thing I’ve learned when working on plugins – especially for profit – is they are likely to change (and by change, I mean grow).

Laying a well-organized foundation and structure from the outset can help guide decision-making later in a project. And this is the main reason I favor using namespaces as early in a project as possible.

The same argument can likely be made for creating interfaces, abstract classes, and the like but those are outside the scope of this post.

Autoloading

There are a couple of different ways we can use autoloading. That is, we can write our own and include it with our plugin or we can use something like Composer (or we can even do both, but that’s not the point).

WordPress Plugin Design: Autoloading

How you opt to include autoloading is secondary to whether or not you opt to use autoloading or not. And just as with namespaces, I ask:

Is autoloading something we should use in small projects?

For a long time, I wasn’t necessarily sold on it for smaller plugins. Sure, you can use the same argument as with namespaces in that it helps guide future decision-making. But I don’t consider autoloading part of the architecture decision-making process.

Instead, autoloading is a utility. It provides us a level of convenience that prevents us from littering our code with including or requiring various files from all over the plugin’s directory structure.

Instead, we include an autoloader and then let it take care of the rest regardless of if we have existing files or files yet to be introduced.

Ultimately, it allows us to write a single function we can use from the beginning of a project and have it scale with our work as we introduce more namespaces and, thus, more classes. And this is the main reason I like using autoloaders as early as possible.

Again, regardless of how you opt to employ an autoloader doesn’t matter so much as whether or not you use them. And it doesn’t matter if you’re using them for just a couple of files or a more complex plugin, they pay dividends the larger your project gets.

Two of Many

There are many other things worth asking about when we should introduce certain features, tools, or strategies. Sometimes, it’s easy to anticipate what a project may require. Other times, it’s not (especially since we usually know the least about a project at the beginning).

But there are things that can make architecture and productivity a bit more efficient regardless of how much we know or how much functionality we’re building at the beginning of a project.

That is, we generally have an idea of how we’re going to organize our directories, files, assets, etc. And if we know that and we want to move forward with adding additional files to our projects with as little friction as possible, why not get started with that as early as possible?

Category:
Articles
Tags:

Join the conversation! 10 Comments

  1. Hey Tom,

    As I’m not doing public plugins, but rather plugins for client work, I’m using both namespaces and autoloading in everything I do. They also complement each other, and if you’re using PSR-4, it all just makes sense (folders & files exactly matching namespaces and classes).

    Even in the simplest plugins, I use pretty much the same boilerplate setup every time, so even the simplest plugins end up having namespaces and autoloaders.

    Also, I include the namespaces in everything, even within PHP templates or configuration files. I do this to avoid unpleasant surprises where different files end up using different classes for the same purpose.

    Also, to keep everything consistent and immediately notice when I’ve screwed up, I use some conventions for the namespaces. I start with the “vendor” prefix, which is BrightNucleus for me. Then I add the “package” prefix, like ExamplePlugin. After that comes the plugin-internal structure. All the classes go into the src folder and are mapped to that “vendor”/”package”/ prefix. So, the file src/Account/UserAccount defines the BrightNucleus\ExamplePlugin\Account\UserAccount class. My configuration files then reuse that same hierarchy, so that I have an easy way of finding the correct configuration sub-tree for a given class.

    I do have to say, though, that namespaces were more of a hassle when I was still working in SublimeText. I used them, but they were costly in terms of pure “code wrangling”. With a proper IDE, however, all the tedious stuff just gets done automatically, so as soon as you start typing a class name, you can let your IDE import the fully qualified class name within your use block at the top. This saves huge amounts of time you otherwise spend just keeping the imports up-to-date.

    Cheers!

    • Alain, I always appreciate your advice for OOP practices with WP. Also have been following your convo in the core autoloader ticket at trac. Thanks for giving back.

      Do youhave a plugin boilerplate with autoloading and all? Would love to take a look at it.

      • Hey Ahmad,

        Thanks for the nice feedback!

        I haven’t finished my WP plugin boilerplate yet. I have a boilerplate for Composer packages you can see here: brightnucleus/boilerplate. The WP plugin boilerplate I’m working on takes this base for an entire plugin, and adds question to determine what types of features to provide (“Does the plugin have dependencies? Does the plugin use shortcodes? Does the plugin use a Settings page?”) and then creates a new plugin using these options.

        I’ll try to remember to let you know as soon as that one is ready to be used.

  2. Hi,

    I’m doing the opposite. I was doing everything with Autoloading and composer by default. But decided to move back and just require php files. While using composer many ideas came to my mind to implement as composer packages and reuse later within themes or plugins, but implementing and using them are usually harder to implement once everything must run within the theme or plugin context. So it was very common to have some cool idea and throw it away. It’s not so easy as you initially thougth.

    Unfortunately for me is better to keep simple for now. But about the Namespaces I agree, is something we can start from scratch with them.

    • Hi Thiago,

      While using composer many ideas came to my mind to implement as composer packages and reuse later within themes or plugins, but implementing and using them are usually harder to implement once everything must run within the theme or plugin context.

      May I ask what the specific problem was you were encountering? My experience is that Composer is the main reason why I can implement as many ideas as I can come up with, so I have made kind of the opposite experience.

      • Hi Alain,

        When enqueueing the stylesheet or script, where exactly the script or style is? Is it within the vendor of the theme, plugin or site (wp installed with composer)? So should I write a custom package just to resolve this? But what is the right choice if many plugins has its own composer.json? Should this all deps be downloaded into plugin/vendor or site/vendor? I think that its too many questions, very easy to make wrong decisions for now. I prefer to wait a little more. Doing things with composer is not so hard, but there many variables to be discussed yet.

        • Hi Thiago,

          First of all, when pulling in a WordPress plugin or theme through Composer, their "type" should be set to "wordpress-plugin" / "wordpress-theme" respectively. If you then add the "composer/installers" package as well, Composer will not install these plugins/themes into a vendor folder, but rather into the wp-content/plugins or wp-content/themes folders.

          If you work with libraries (which are meant to be consumed directly by another library or plugin, not by WordPress itself, as a plugin is), then it gets indeed a bit more complicated. Composer is meant to manage source code, not assets. There are ways to deal with this, but they then work around WordPress folder hierarchy. So, when you’re building custom WordPress functionality, my recommendation is to have all the reusable (from project to project) code in libraries/Composer packages, and then have wrapping plugins as Composer packages with the "wordpress-plugin" type that consume these libraries and contain the stylesheets/scripts. This way, all your assets will still end up in wp-content/plugins and can easily be enqueued.

          For a look at a more universal package manager for PHP that includes asset management (and reuses Composer for code), visit http://docs.puli.io/en/latest/#

          • Hi,

            my point was exactly libraries. How you have explained, it’s very complex to work with assets. I do not agree with you about composer to not manage assets… composer itself says it can package other things different than PHP code.

            Anyway, I think that creating a library to be a dependency of a plugin or theme maybe is too much for me. This is why I moved back to simplicity.

            Thanks for sharing your experience ;)

            Thiago

            • Of course you can add whatever you want to a Composer package. However, one of the core principles of Composer is that you should not need to know about the exact location of the “vendor” folder (which can be renamed/moved) and not rely on it always being in the same place.

              This is perfectly fine for backend (server) code, as they can, for example, use such constructs as __DIR__ to use relative paths to point to their resources.

              However, this does not work for the frontend, where you need to provide absolute path mappings that translate from backend location to frontend location (/srv/www/images/1.png => https://mydomain.com/images/1.png). For the frontend, you need to be able to rely on fixed paths that don’t change or move for this mapping to work. The Composer vendor folder could even be outside of your web root, so that there is not even any access from the frontend possible.

              So, yes, you can manage whatever you want with Composer, but you’ll only be able to easily use it on the backend. It’s the same reason of why most people use both npm and bower for their JavaScript packages. bower puts the packages in a place and structure that can be meaningfully retrieved from the frontend.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.