Namespaces in WordPress: File Organization

Those who have worked in object-oriented programming languages are likely familiar with namespacing and the benefits they provide when organizing a project. Unfortunately, namespaces in WordPress aren’t something that I’ve seen as much as in projects I’ve seen elsewhere.

Namespaces in WordPress: File Organization

And when I say “namespaces in WordPress,” I’m not talking about WordPress core. I’m talking about WordPress plugins. I think there are a variety of reasons developers don’t use namespaces (and may I’ll talk about those later); however, I’ve gotten curious about those who do use namespaces in their projects.

Specifically, I’ve been interested in the conventions that people follow, how they map their files to their namespaces, and so on.

Though there’s likely variation in some of the things we do, I think making sure our files map to a particular directory structure is helpful when dealing with projects (especially large projects).

Namespaces in WordPress

Nothing in this post assumes you use namespaces, but to make sure you know the definition off of which I’m working here’s the definition from the PHP manual:

PHP Namespaces provide a way in which to group related classes, interfaces, functions and constants.

Yeah, it’s fun to take a more nuanced approach and discuss just how far we should take this idea. But that’s for a face-to-face conversation with a fellow developer over coffee at a conference, right?

Though I’ve not always used namespaces in WordPress for many of my public projects, I do for those I work on for clients (and I’ll talk about this more in just a bit). And the more I’ve done this, the more I’m a fan of making sure that the namespaces also match the directory structure.

Directories and Namespaces

Sometimes, developers will refer to namespaces as “virtual paths” which assumes the file organization is the physical path. That’s yet another opportunity to be pedantic, but for the sake of conversation, I think it’s important to have that distinction.

For me, I like to organize my files in the project directory following the same hierarchy as the namespaces defined in the code.

Namespaces in WordPress: Project Files

This means that if a class is in the Acme_Project\Admin namespace, then I can find the file in the acme-project\admin directory.

Similarly, if I’m working with a file that renders a page in the WordPress administration area and it’s in the admin-project\admin\views directory, then it’s namespace should map to Acme_Project\Admin\Views.

This Isn’t To Scale

The example given is pretty simple (maybe it’s too simple?), but the benefits come when working on a large project with a lot of files, a lot of directories, and a lot of moving pieces.

It helps to have a convention that maps the project’s organization on disk to the project’s organization in code (and this is particularly useful when debugging).

If it’s something that’s defined from the outset, you almost intuitively know where to place the classes in the project as you work on the codebase.

13 Replies to “Namespaces in WordPress: File Organization”

  1. It’s worth mentioning that this technique can make autoloading your classes easier, and if you follow a standard like PSR-4 it opens the door to tools like Composer that can generate an autoloader for you.

    1. This is one thing I was looking at talking about in a future post (that is, getting composer to generate the autoloaders), but I was going to tackle manually writing autoloaders.

      I don’t think manually writing autoloaders is all that great, but it definitely helps cut down on all of the include and require statements than can exist in code.

      Using a package manager is even better (and cleaner, in many cases). But it comes with its own learning curve, as well.

  2. Hi Tom, glad to see more people writing about modern PHP dev topics.

    We’re introducing namespacing in AffiliateWP 1.9, and it’s proven to be an interesting challenge integrating that flow into legacy code. We obviously can’t break back-compat with established logic, so it feels a bit disjointed, but we also know it’s the right path forward.

    API design can be interesting, especially when you’re considering a large ecosystem of third-party extensions as we are. It really forces you to put the “abstraction” in abstraction layer (and test test test #allthethings).

    Actually, the funny thing is that the new objects we’re introducing aren’t really exposed beyond the caching layer, so we were initially aliasing namespaces outside the object code but found that aliasing solely for the benefit of inline documentation was kind of silly – especially as docs are typically where you want 100 percent clarity. I think that’s a super interesting topic, btw, whether verbosity in typing for inline docs should fall within the scope of namespace aliasing or whether that’s doing a disservice to first- and third-party developers.

    Thankfully AffiliateWP is PHP 5.3 minimum so that really opens a lot of doors to introducing a more modern, dynamic underbelly. I’m looking forward to extending the fingers of namespaces further into this code base.

    1. We’re introducing namespacing in AffiliateWP 1.9, and it’s proven to be an interesting challenge integrating that flow into legacy code. We obviously can’t break back-compat with established logic, so it feels a bit disjointed, but we also know it’s the right path forward.

      This is neat that you’re bringing this up. I was just talking with Pippin about backwards compatibility issues at WordCamp San Diego – it was over something else (specifically what happens when you want to change the name of a hook or something like that) but this still ends up raising the same questions.

      And that is, how do you deal with it and how do you handle deprecating the code and then giving users a heads up about it?

      I assume with AffiliateWP (granted, I’ve never written anything against it) that it doesn’t have as many hooks as something like EDD, but that doesn’t mean it’s not without its challenges.

      It really forces you to put the “abstraction” in abstraction layer (and test test test #allthethings).

      Right? That’s one thing that always stays in my mind when iterating on a project.

      Case in point: I’m working on a project for a client right now where it’s heavily namespaced and it’s using generally proper OO concepts, but in order to make sure I’m not getting stuck up in the atmosphere like an architecture astronaut, I tend to get the plugin working and then send it over for user testing. While that’s happening, I then begin to introduce abstraction and refactoring some of the classes.

      This is probably a topic of an entirely other blog post, though.

      I think that’s a super interesting topic, btw, whether verbosity in typing for inline docs should fall within the scope of namespace aliasing or whether that’s doing a disservice to first- and third-party developers.

      This is one of those confessions that always sounds kind of dorky to make, but last night when I was getting ready to bed I was thinking about documentation (primarily in the form of code comments and DocBlocks) and how verbose they should be.

      I’ve been told that my comments are often too verbose but then I see the work others have done that are very, very long but that exude such clarity that it doesn’t leave me asking any questions and that’s where I think I’d ultimately like to be.

      Thankfully AffiliateWP is PHP 5.3 minimum so that really opens a lot of doors to introducing a more modern, dynamic underbelly.

      As much as I’m enjoying PHP7 (and even 5.6, TBH), I’m about ready just to set all future projects to be set at PHP 5.3 just so I can take advantage of some of the features like namespacing for the sake of better code organization and for the ability to use composer to create an autoloader.

      Having to manually write them isn’t bad, per se, but it “feels” tacked on and little weird especially when coming from other languages that will dynamically figure it out based on the organization of a project.

      But I digress on that for now.

      Thanks for this comment, Drew. Love hearing how other people like you guys are handling this.

  3. Hey Tom,

    I use PSR-4 in my code (Dylan already linked to it above).

    In my root plugin folder, I only have 1 single file, which I call my plugin bootstrap file. This file contains the plugin metadata, loads the autoloader (generated through Composer), and kicks off the main “Controller/Plugin/Core” class by injecting a configuration into it. Injecting the configuration through the plugin bootstrap file allows me to also provide an alternative test bootstrap file that might inject a different configuration better adapted for tests (like a mock DB, mock network connections, …).

    My classes normally go into a src subfolder, which is mapped in composer.json file to the plugin’s root namespace, like BrightNucleus\ExamplePlugin. If I have a class in a sub-Namespace, like BrightNucleus\ExamplePlugin\Database\AbstractRepository, that file is located in src/Database/AbstractRepository.php.

    I find it important to separate the bootstrapping process (make it ready for the current environment) from the actual functionality (let it do the actual job it is meant to do). That’s why I only ever have bootstrapping code in the main plugin file (the one that WordPress parses in the plugin’s root folder).

    With all that said, it is important to note that what I describe above partially goes against what the WordPress Coding Standards prescribe. I generally code to PSR standards, except for the code that directly integrates with WordPress. With that code, I try to adhere to WordPress Coding Standards as long as this does not hinder in applying PSR in the surrounding code (like with the namespaces, which are used outside of WordPress too, as most of my libraries are framework agnostic). And, very generally, I really dislike WPCS class file naming. ;)

    1. I totally agree. I’ve been using the PSR-4 standards now too, and I cringe every time I have break the standards to conform to the WPCS.

      I’d love to see the WPCS be brought up to modern coding standards, but whenever someone mentions updating the core code there’s always the “We can’t do that because of backwards compatibility” excuse. Which is total BS. It’ll be more work to make it all backwards compatible, but it’s not impossible to do.

      As for the namespacing. I love it. I write cleaner code because I have to really thing about what ges in a file. It’s not the like writing the spaghetti code of days past.

      The only issue I ever have is working with the WP hooks. It get a little tricky sometimes.

      1. I totally agree. I’ve been using the PSR-4 standards now too, and I cringe every time I have break the standards to conform to the WPCS.

        I’m not at the point where I cringe yet because I’m still towing the line. But I’m hitting up against it, for sure.

        I’m just trying to be patient and thoughtful about where I want to go from here.

        Which is total BS. It’ll be more work to make it all backwards compatible, but it’s not impossible to do.

        That’s a kind of weird excuse in this case. To me, at least. And here’s why: It’s one thing to refactor an entire codebase (or even a portion of it) because of backwards compatibility.

        But introducing certain things that are compliant with both PSR and with the lowest version of PHP submitted doesn’t seem to because a conflict.

        Maybe I’m missing something.

        I don’t disagree on maintaining backwards compatibility, but I do when it comes to relying on it as a crutch for not wanting to make changes.

        As for the namespacing. I love it. I write cleaner code because I have to really thing about what ges in a file. It’s not the like writing the spaghetti code of days past.

        Namespaces + OO is fantastic, isn’t it?

        The only issue I ever have is working with the WP hooks. It get a little tricky sometimes.

        Yeah – that’s where I think Alain’s comment begins to hit on the same topic. I’m still working through that myself.

        I’ll probably write about what I’m doing at some point to handle that, but I feel like I’m still in kind of an exploratory period of trying out what I like that most.

    2. I use PSR-4 in my code (Dylan already linked to it above).

      I’m so conflicted on whether or not I want to go full on PSR-anything. I’ve always been such a proponent for the WordPress Coding Standards for a number of reasons (usually the whole “when in Rome…”) but I’m at a point where I’m starting to get a little more restricted by it.

      So then we face this issue: Have 100% coding standard compatibility with WordPress standards, which I think are important. But the quality of code applied via PSR-4 is so much cleaner. It really can take some of the hated aspects of PHP (which are neither here nor there for me personally) and make it a more elegant way to write PHP code.

      n my root plugin folder, I only have 1 single file, which I call my plugin bootstrap file. This file contains the plugin metadata, loads the autoloader (generated through Composer), and kicks off the main “Controller/Plugin/Core” class by injecting a configuration into it.

      Your approach is more mature than mine right now. Though I’m still 100% for a bootstrap file and having the rest of the plugin setup in a src folder or even divided among admin and public folders, I’m not yet having Composer handle the autoloading.

      Soon, but not right now. Gotta balance constraints and deadlines with all of this.

      I find it important to separate the bootstrapping process (make it ready for the current environment) from the actual functionality (let it do the actual job it is meant to do).

      Agreed. Absolutely on point.

      With all that said, it is important to note that what I describe above partially goes against what the WordPress Coding Standards prescribe. I generally code to PSR standards, except for the code that directly integrates with WordPress.

      So do you just forgo WCS when sniffing your code (if you sniff your code) and then just use standard PSR rules?

      I mean, I know you say “except the code that integrates with WordPress,” so I’m just curious how you handle the set up to exclude certain files, etc.

      That’s kind of a happy balanace in my opinion.

      (like with the namespaces, which are used outside of WordPress too, as most of my libraries are framework agnostic)

      The way I have my sniffer set up, it doesn’t yell about namespaces so that’s nice :). I can use those and the WPCS doesn’t say anything about them.

      And, very generally, I really dislike WPCS class file naming. ;)

      Yeah. It’s one of those things I just accept for now. Again with the “when in Rome” kind of thing, but maybe I’ll come around.

      I don’t know. Lots to think about it.

      As always :).

      1. So do you just forgo WCS when sniffing your code (if you sniff your code) and then just use standard PSR rules?

        I mean, I know you say “except the code that integrates with WordPress,” so I’m just curious how you handle the set up to exclude certain files, etc.

        As you might already have noticed, I’m all about having clear separations and modularity. As a general rule, I split code up into its responsibilities, and this already takes care of the above problem.

        As an example: Let’s say I need to add API client functionality to a WordPress site. The site needs to read some data from an external API, and then display that data in a WP backend options page.

        This is clearly two separate problems to me:

        read and manipulate REST API data;
        display given data in WP backend.

        So, I build two different packages for each of these responsibilities. One is general PHP code, it will be coded in PSR-2. The other is WP integration code, it will be coded in WPCS. The second one just pulls in the first one as a Composer dependency.

        So, both can be completely checked against their actual requirements, without any exclusions or other special cases. They also have separate lifecycles, which is preferable, as they depend on different contexts and requirements.

        Integrating something into WordPress is a specific, separate responsibility in my eyes. I don’t think in WordPress plugins, I think in PHP code, that might end up being used by the WordPress framework through a WP plugin integration.

        Hope this was clear enough to follow…

  4. I believe the WordPress Coding Standards predate PHP-FIG by a good few years which could explain why the general WordPress community is yet to adopt the PSR-4 recommendation. Perhaps plugin authors are also committed to supporting PHP 5.2 (namespacing being a PHP 5.3+ thing)?

    +1 to your approach, I hope this is soon adopted by the entire WordPress community (plugin authors and core).

    1. So true.

      I think future plugin authors should make a min of php 5.3 for all projects. Force outdated WordPress installs to update. Sorta like the browser warning for IE a few years back.

      Php 5.4 has some nice shorthand. Rather avoid that for now and move towards 7. Same code, just future ready.

      Namespacing is great for referencing, auto loading, path navigation, importing, etc.

      Add in a Pimple container with an autoloader, maybe a new boilerplate? If WordPress doesn’t keep up, heck, code a service wrapper for that functionality.

      1. I think future plugin authors should make a min of php 5.3 for all projects. Force outdated WordPress installs to update. Sorta like the browser warning for IE a few years back.

        I like the idea of using 5.3 for plugins, but not at the expense of WordPress installs (unless you’re talking about very old versions but that’s a whole other area I definitely don’t want to touch :).

        Php 5.4 has some nice shorthand. Rather avoid that for now and move towards 7. Same code, just future ready.

        7 is so nice, imho. Performance-wise, especially.

        Namespacing is great for referencing, auto loading, path navigation, importing, etc.

        Yes sir!

        Add in a Pimple container with an autoloader, maybe a new boilerplate? If WordPress doesn’t keep up, heck, code a service wrapper for that functionality.

        WordPress will keep up, i imagine, but on its own timeline. They are pretty good about a number of things but it’s important to remember it’s a legacy app, you know?

        Even still, you suggeestions aren’t bad nor off point.

    2. I believe the WordPress Coding Standards predate PHP-FIG by a good few years which could explain why the general WordPress community is yet to adopt the PSR-4 recommendation.

      You’re right that it pre-dates it, but the reason it has yet to adopt it — at least the wider development community — is probably due to a number of different reasons.

      Some of these are likely:

      • Education
      • Reading Tutorials (some of which I probably should go back and edit)
      • Lack of awareness
      • etc.

      +1 to your approach, I hope this is soon adopted by the entire WordPress community (plugin authors and core).

      My approach is still in the works but I’m getting there!

Leave a Reply

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