One of the points of discussion that often comes up among software developers is how to best organize code and files within a project.

Some frameworks enforce for you to follow an organization scheme – such as Rails which prizes “convention over configuration” – and then other foundations, like WordPress, have standards for certain things – like markup and PHP – but don’t have standards for other things.

For example, there’s no real standard on how to name your stylesheet or JavaScript directories. There’s no standard for where libraries should be kept, nor is there a standard for where preprocessed or pre-minified files should be kept.

Sure, most of us have opinions on this, and developers often spend a lot of time (perhaps more time than they’d like to admit) thinking about optimal ways to organize this information, whereas others are happy to dump things in a directory and as long as the project has some semblance of organization (even if it makes sense only to them), they’re good to go.

Granted, there are personality traits at play here, but I digress.

I’m of the former case where I prefer to try to make sure things are highly organized – perhaps to my own detriment – and I try to bring the idea of “convention over configuration” to work I do within plugins and themes.

And though I spend more time talking about plugins, general practices, and other topics here, there are a few guidelines that I’ve been following as it relates to WordPress theme development that I’ve used in both my own projects as well as contract work.

Organizing WordPress Theme Functions

Talking about how to best organize the files that make up a WordPress theme is a lengthy series unto itself, and it brings with it a level of subjectivity that’s not worth trying to discuss in a single post.

However, there have been a few things that I’ve begun to implement as it relates to functions.php and other related files that contribute to the core of a WordPress theme. I’ve been using them in a number of projects and I’ve found that it helps to provide some type of organization in a space where it’s really easy to lose track of where certain types of functions reside.

Separation by Function Type

In object-oriented programming, there’s this notion of separation of concerns (which I’ve discussed around templates and queries); however, I don’t see this used as much in the context of procedural programming.

Admittedly, I’ve done far less procedural programming in my career so I could be completely ignorant on the topic, but it seems that it’s a more widely accepted practice to have giant files with collections of functions that aren’t necessarily related.

In WordPress, this is often functions.php.

But there are certainly ways to keep the files separated and organized in such a way that’s they show a bit more cohesion than just dumping them into one big file.

Organizing Theme Functions

As with anything programming related, this has potential to change in the future; however, here’s the organization scheme that I’ve found most useful for organizing WordPress theme functions.

Mayer Theme Functions

Here’s an survey of how I’ve broken things down in Mayer. Obviously, this isn’t going to be one-to-one with every theme, but the principles still apply.

  • functions.php. This includes a constant for tracking the theme version, require_once statements to bring in any dependencies (listed below), then hooks that are directly related the theme features, stylesheets, JavaScript, and comment-related functionality.
  • inc. This is a directory that contains files that are imported via the call to require_once call in functions.php. It’s meant to hold files that contribute to the theme, but aren’t part of the core theme hooks.
  • inc/helpers.php. These are functions that are used throughout the theme’s template files to help make the code more readable, and to abstract some of the core WordPress logic out of template files.
  • inc/class-theme-nav-walker.php. This class provides formatting for custom navigation in a theme.
  • inc/theme-customizer.php. This file includes all of the functionality necessary to utilize the WordPress theme customizer.
  • inc/wpcom.php. If the theme is going to be released on WordPress.com, then this file includes functionality specific to that environment.

Again, this is but one example of how I’ve found things to be useful.

For what it’s worth, I generally have functions.php, and inc directory, a helpers.php file, and then the rest are determined based on the features of the theme.

There’s No Single Best Strategy

Ultimately, the idea behind all of this is to bring a bit of cohesion to a relatively unorganized space.

Regardless of the ways in which you build your projects, the ability to maintain them over a long period of time matters. Making sure that you’re organizing things in a logic, conventional, and consistent way and go a long way in helping to do that.

With that said, I’m always curious for how others have gone about organizing their files, so if you’ve got an alternative way to do it, or something to add to the scheme above, then I’m all ears.

Otherwise, hopefully this helps with those of you looking to bring some way to wrangled your theme files into submission.

Category:
Articles
Tags:

Join the conversation! 19 Comments

  1. I do not get why people do not use objects in the functions.php? I know that the functions.php file itself cannot be OO but if you called into an object from the functions.php then I do not see why this would be a bad strategy to take. However when you look at the code in themes this type of strategy is not at all popular. I just do not see why?

    • This is a bit of a technical reply, but I want to try to keep it relatively short.

      Themes and Plugins and different, so where it’s easy to introduce object-oriented principles into plugins, it’s not possible (or advisable, in my opinion) in themes.

      This is primarily because themes extend the WordPress presentation layer or, more technically speaking, the page load lifecycle which is driven by the event-driven design pattern. To that end, functions need to be setup as callbacks hooked to functions that are related to pages.

      A similar analogy is with the old .NET WebForm model: We used to setup functions that dealt with certain functions during the page load life cycle, but the Page itself was an object. That’s not the case in WordPress.

      So, to that end, trying to even think how to introduce objects into the context of themes (outside of plugins or libraries) feels very odd.

  2. Over the past couple of years I’ve really put an effort into organizing my files, codes, etc, for myself as well as my client projects. In doing that, I’ve found a couple of things stand out:

    /css/, /inc/ and /js/ folders are a must with my work flow now. I’d be lost without them keeping things organized.
    Organizing my code files, functions, etc make things so much easier to go back and edit, or explain to someone how things work, rather than saying: “it’s in the functions.php file”.

    Just like code commenting has become a larger part of my workflow, so has organizing files. I don’t believe I have the best setup yet and I’m constantly tweaking it to make sure things are as clean as possible, but it’s definitely better than 1,000+ lines in the functions.php file :)

  3. Something I struggled with for a while was admin file organization…

    I have an inc folder in my themes too, and usually add a css, js, and admin folder in it. My thought process was “should I put admin JS in the inc/js, or create a new JS folder for it in inc/admin?!”.

    I think I was just overcomplicating things for a while, but I ended up keeping everything in the single inc/js/inc/css.

    • I did the same thing recently with the /inc/ folder and needing to add a bunch of different loop files for post types, wondering if I should add a folder within the /inc/ to separate the loop files from the other files I needed. I think I may have been over complicating things a bit, too.

      • Personally, for loop-related files, I think of partials or perhaps content because this allows you to setup code that calls get_template_part( 'content-image' ); for a content type (assuming you’re talking about post formats :).

        I think I may have been over complicating things a bit, too.

        This always happens to programmers – myself included – and I don’t have a great idea on how to change this, but perhaps it’s something I can bring up in a future post.

    • Personally, I organize my files in terms of admin and public and then there is admin/css, admin/js, and admin/partials and so on.

      There’s more to it than that, but you can get a feel for how I organize some of this stuff with the Plugin Boilerplate.

  4. I absolutely agonize over stuff like this.

    I’ve finally settled on inc for internal dependencies and lib for external dependencies from Bower and Composer.

    Whether that’s right, wrong, or otherwise, I feel good about that.

    • I know that feel. Of course, this post was inspired by some of the conversions that we’ve had, so there’s that :).

      Similar to you, there’s still inc and includes and lib and vendor, all of which I like, none of which I’ve actually settled on.

      Whether that’s right, wrong, or otherwise, I feel good about that.

      And that’s what it comes down to a lot of time, in my opinion. If you’re able to cleanly organize your files and easily move throughout your project, then you’ve got it organized in a good way.

  5. Such great timing on this. I’ve long agonized over this issue, but right now I’m building a complex site for a client and still moving pieces around trying to find “the right” organization.

    I like the idea of a helpers.php include though. I’d be curious to see specific examples as to what goes in helpers vs functions.

    Personally, I do put some files in /inc’s just like you for things like nav walkers, social buttons, large functional components.

    • Such great timing on this. I’ve long agonized over this issue, but right now I’m building a complex site for a client and still moving pieces around trying to find “the right” organization

      I think this is every developer’s curse. We’re constantly in pursuit of the single “right” solution of the absolute “best” solution when, I don’t believe, it exists at all.

      In fact, we’re just constantly trading off pros and cons until we’ve maximized our pros (and we still have a few cons).

      I like the idea of a helpers.php include though. I’d be curious to see specific examples as to what goes in helpers vs functions.

      I think this is a good example for a future post – I’ll try to follow up with this soon! Thanks for the idea.

  6. I too have spent way too much time with this sort of thing in general which, funny enough, seems to be forever getting tweaked. Having said that, I have adopted the approach that the Roots theme uses with functions.php included from /lib, specific /templates folder and /assets that include all my js, CSS and LESS/SASS files that my task runner builds from. Even on non WP projects, I use a very similar organization so I can always jump back into projects down the road and it’s all fairly familiar.

    • Yeah – I’m with you in that whatever organizational scheme I use in WordPress projects often transcends the type of project on which I’m working.

      That is, if it’s a vanilla site without a framework or some type of middleware or backend, I still organize the frontend aspects of my work much the same way if for no other reason than it takes the mental taxation out of remembering how I organized files across projects :).

      • Quick question in regards to “vanilla site with no framework”… Since switching over to responsive coding several years ago, I’m finding it harder and harder to justify not using a framework (primarily TB) on just about any project other than the very minimal landing page or coming soon page. I find that I can build stuff at least twice as fast, cross browser and device testing/debugging is faster, etc.For years before frameworks, the start of my project always included setting up a quasi framework (default styles for elements, resets, typography defaults, etc.) and I now see using a framework as simply not writing by hand what’s already been written.

        The problem I have is that at times I feel that the framework saves so much time that I feel guilty charging what I do. I’m interested to hear if anyone else experiences this.

        • Quick question in regards to “vanilla site with no framework”… Since switching over to responsive coding several years ago, I’m finding it harder and harder to justify not using a framework

          I should’ve clarified that I meant a backend framework (such as Rails, Yii, or something like that). These days, you’re right, it’s increasingly more difficult not to use a front-end framework.

          The problem I have is that at times I feel that the framework saves so much time that I feel guilty charging what I do. I’m interested to hear if anyone else experiences this.

          It’d be one thing if you were churning out projects that all looked the exact same save for a logo image, but there’s nothing wrong using a grid and other minor styles to help normalize our pages any more than it is to serve dinner on plates that all look the same: It’s the features and functionality and presentation that they’re paying for, not the foundation upon which it sits :).

  7. Sincerely by the title I was expecting a bit more on structuring files and functions in a WP theme, there are so many more aspects of it, we could argue for months ^__^ . But I do understand that’s a very tricky topic. Thanks for writing this up, Tom. I specially liked the digression about plugins being different than themes regarding a full OOP implementation in one of the comments.

    • Sincerely by the title I was expecting a bit more on structuring files and functions in a WP theme, there are so many more aspects of it, we could argue for months ^__^ .

      You’re right, and this is not likely the last time that I’ll talk about this either :).

      Thanks for writing this up, Tom. I specially liked the digression about plugins being different than themes regarding a full OOP implementation in one of the comments.

      Thanks – I appreciate that! It’s one of those things that requires a bit of a mental shift when you’re thinking about WordPress and the type of things that you’re building. Perhaps a post in and of itself :).

  8. Hi,

    Great article. I to drastically over think the organisation of my files. I have used lots of different ways, Inc folder, all in the functions etc. Now I have created a plugin where all my theme’s functions live. Everything that is not directly linked to the theme goes into the plugin. The plugin has it’s own include folder with stuff for sidebars, navigation, custom post types, or whatever is required for that project and a master plugin page which includes these files, commented out if not needed.

    Most of my themes are pretty much built with exactly the same code and I use my stylesheet to change the look of the website. As features change in each project so I just comment out or exclude any relevant includes in my plugin that I won’t need.

    Whilst not completely finished yet, it seems to be making a great deal of difference in time it takes to create my themes. Which is always a good thing. All the functionality is there, so I get to spend more time on the design side of things for my clients.

    Keep up the great articles, love reading them.

    • Whilst not completely finished yet, it seems to be making a great deal of difference in time it takes to create my themes. Which is always a good thing. All the functionality is there, so I get to spend more time on the design side of things for my clients.

      Exactly – if you can get to the point where you’re streamlining your workflow such that it allows you to get up and running faster with the main focus that you have, then I think you’re making progress.

      I appreciate the compliment!

Leave a Reply

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