Core Functionality Plugin

As described in more detail by others (Otto, WPCandy…), a WordPress theme should only contain that which relates to the look and feel of the site. Any core functionality belongs in a plugin.

A good rule-of-thumb is that anything a user would expect to keep after changing themes belongs in a plugin. This includes custom post types, taxonomies, metaboxes, shortcodes, and customizations to other plugins (like my Display Posts Shortcode snippets).

For specific functionality that’s reusable and/or the client might want to selectively disable, it’s best to build as its own plugin. Many times I’ll turn these into public plugins.

For everything else that’s project-specific but should be theme-independent, I put in a plugin called Core Functionality. Of course you’ll want to delete everything that’s not relevant – I have the code for post types, taxonomies, and metaboxes in there because they are used most often.

Tutorial

Receive New Posts by Email

Comments

    1. Yep, I do this as well. The only issue is mu-plugins doesn’t look within folders. So instead of dropping /core-functionality in there, You have to drop the contents of your core functionality plugin directly in the mu-plugins directory.

  1. Bill,
    I enjoy your site. I have used your rotator and ‘Rotator Options’ metabox before, so I thought I would give your plugin a try. Sounds like a really good idea. I used your child theme and plugin. The rotator metabox loads and the ‘Instructions’ are saved but do not display with the ‘Featured Image’ on my localhost. I do not want to waste your time, and I do not have the time to look into it further, but I thought at least I should say something. I reinstalled it and got the same result.

    Keep On Trucking!

    1. Make sure the field ID’s you’re saving are the same that the rotator is pulling.

      WP Rotator uses wp_rotator_url and wp_rotator_show_info for custom field names. The Custom Functionality plugin has be_rotator_url and be_rotator_show_info.

      This is just sample data and isn’t designed specifically to work with WP Rotator. But if you change be_ to wp_ it will.

  2. About MU-plugins, it is possible to use a folder for each plugin.If you make an include file in your MU-plugins folder.

    Here is the snippet, I’m not sure about how to list code, so I have excluded the tags.

    Include.php
    ?php
    include (‘plugin_folder_name/file_name.php’);
    ?

    1. Yep, that’s definitely an option. But the way I look at it, the plugin.php file in /core-functionality does exactly that. It simply includes all the relevant files. So I drop plugin.php in /mu-plugins which just includes all my files, and everything else is in /mu-plugins/lib

  3. Great points. I get frustrated with the direction themes seem to be taking, where a ton of functionality is written directly into the theme. And frequently, it’s hard to tease out the functionality due to pieces being in various places – page template, functions.php, header.php, etc. Woothemes makes great themes, but I don’t understand why they don’t create plugins a la faultpress, wikeasi, supportpress, etc. Additionally, they created a decent framework/theme, but haven’t based any of there own themes on that framework. I appreciate you sharing this, as I think this gives a good basis and maybe a step in the right direction for theme developers.

  4. Really nice post Bill. If I might, how do you handle things like single-{post-type}.php, archive-{post-type}.php, taxonomy-{taxonomy}.php. I had thought about moving my custom post-types and taxonomies to a core functionality plugin, but was unsure how to handle these templates since they would be dependent on the core functionality plugin.

    Also, the mu-plugins idea doesn’t work so well for a network environment where not all sites require the extra functionality.

    1. The registering of the custom post types and taxonomies belong in the functionality plugin, but their display (the template files) belong in the theme. Besides there not being an easy way to package theme files in a plugin, the idea is that if you change themes you’d need to change those theme files as well.

      I don’t work on multisite websites, so that’s not an issue for me 🙂

      1. That is kind of what I concluded from my investigations.

        I maintain four network installs. All for the same university. 🙁

  5. Hi, Bill – just wanted to thank you for this and your other post on Custom Post Types. What you’ve described about a core functionality plugin makes a lot of sense and I’d never thought about it before. I’m about to start experimenting with Custom Post Types for the first time and happened upon your site – great instructions and advice.

  6. How come there are no shortcodes listed in https://github.com/billerickson/Core-Functionality? I always use the url, wpurl, and child shortcodes that I learned from your site and include them in every project. I recently switched to using a Core Functionality plugin (which I also first heard of on your site) for non-theme related things and I just added a shortcodes.php file to the /lib/functions folder. Is that how you do it when you add shortcodes for a client site?

    1. If shortcodes are required, I create a file in /lib/functions/shortcodes.php.

      A long time ago I used the url, wpurl, and child shortcodes in sidebar widgets because my find/replace of URLs when migrating didn’t work on serialized arrays (widget content is stored as a serialized array). Now that I use this approach, I use actual URLs instead of shortcodes everywhere. I no longer need those three shortcodes.

  7. Thanks for this idea!

    I was curious though; how do you flush the rewrite rules cache when you make CPTs this way? Must Use plugins don’t respond to activation hooks, which is what appears to be the normal method. Do you just go to Settings > Permalinks after you make your CPTs? Calling that page up seems to force a refresh (you stop getting 404s on newly created CPT posts after).

    1. Yes, I go to Settings > Permalinks to flush the rewrite rules. Since this is a plugin developed for a specific client, and I’m the one who’s implementing it for them, I don’t have to worry about the rewrite rules being flushed (the client never activates/deactivates it).

      Thanks for the reminder. I updated the post above to indicate I no longer use must-use plugins for this and why.

      1. Thanks for the reply and update. You make some fair points rationalizing not using this any longer. The first is the most compelling for me.

        I assume you just chunk this out into a regular old plugin then?

  8. Hi Bill

    Someone made custom changes to our original lifestyle theme version 1.0 things like content area wider, and side bars and all the aforementioned borders their colors and width and menu drop down style and look. They did the coding within the actual style sheet etc and possible sometimes php file maybe as well no doubt not the best correct way of doing such changes and wanted to know WHAT one SHOULD have done really when doing such things…

    NOW, if I was to upgrade to lifestyle 2.0 latest everything will look different since we did a test view and the content words and images within the side bars all got totally jumbled and haywire……my FIRST question to you please is what would you say if we did want to upgrade to lifestyle 2.00 how best to go about doing it and where should such custom coding to have wider content side bars look etc be applied to in a way where any future upgrades won’t create the same problem – we have 4 sites all done using same Lifestyle version 1.0 right now and feel upgrading to any future versions we should perhaps be actually doing ? So as to keep everything future proof so to speak

    I am not good with code but willing to make back ups and copy code once I know where to add it in what specific place or plugin you have that may aid and how to use etc.

    many thanks

    1. Making changes to the look and feel of your site (making sidebars wider, changing font colors and sizes…) should always be done in your child theme. It sounds like your developer did it correctly.

      Your child theme contains your site-specific design changes. When I build a site for a client using an existing child theme like Lifestyle, the first thing I do is rename the theme because we know we’ll be changing it.

      Child themes are not designed to be updated. There is no upgrade path from Lifestyle 2.0 from Lifestyle 1. They are two completely different themes.

      If you’d like to use Lifestyle 2.0, you’ll have to take the same approach you did with your first theme: Install the new theme, then hire a developer to make the changes you’d like made to it.

      The core functionality plugin discussed in this post is for theme-independent features. That is, the things you would want to keep if changing to a completely different theme. The widths of sidebars belongs in a theme (design). Things like custom post types belong in a plugin (functionality).

      I hope that helps.

  9. Great tip, Bill, makes sense. I was looking for a way to safeguard code I added to functions.php from theme-changes (having done it manually some times now), but was somewhat afraid to make my own plugins. I now find myself in serious danger of understanding the code you wrote, even the class and object you made, so I am probably ready to try it myself. I understand from the comments you now favor a normal plugin over mu-plugin, and since I don’t build for others yet, it would be the logical choice for me too.

    One question. I have read you use the word rotator several times now, but am not sure what you mean by that. Is that just another word for (image)slider, or something more specific? And is the other word you use elsewhere “flex-slider” again something different, or the same? I might be missing some context here. If you would enlighten me, much appreciated. I understand it might be a bit of a newbie question, sorry for that.

  10. I always thought that too many plugins will make a site slower and use up all the server resources. But you have a point. Coding everything in the theme will cause rewriting of every customizations when changing the theme.
    Will need to look into it further. Do you have any recommendations to avoid having the plugins use up server resource which cause database connection problems in smaller servers?

    1. The number of plugins installed has no effect on server resources. Whether the code is located in a theme, plugin, or 5 plugins doesn’t affect performance – it’s the code itself. One plugin with poor code can slow your site down, which is why it’s important to use high quality plugins that specifically target your needs.

  11. Hi Bill,
    I’ve been using a forked version of your functionality plugin for years. Thanks for putting it together!

    I noticed that you made quite a few changes to the plugin earlier this year. Can you explain why you removed metaboxes.php and CMB?

    Do you not use CMB(2) anymore and do you add metaboxes elsewhere?

    I know you also use ACF. Do you export the fields created in ACF to PHP so you can source control them? That’s what I usually do and keep them in the functionality plugin. Do you see any issues with that?

    Thanks!

    1. I removed CMB2 because the code was out-of-date. When I use CMB2, I install the CMB2 plugin to ensure it’s always using an up-to-date version.

      I tend to use CMB2 for most metaboxes, and ACF for very complex ones – specifically ones requiring tabbed content, or multi-section landing pages leveraging the Flexible Content field type.

      If a site requires one ACF metabox and one or two others, I’ll tend to do everything in ACF just for simplicity. But I still only use it for post meta.

      If a site requires an options page or term meta, I always do that in CMB2 due to the negative performance of ACF in those contexts. Term meta is stored as site options rather than actual term meta. And both term/options are all stored as individual fields rather than a single serialized array. AND they store 2 options for every 1 option you create (they have a separate one for identifying the field). So if you have a few fields including a repeater field on an options page, with CMB2 it is a single option in the DB. With ACF it could be close to 50 options.

      Also, I never use the ACF frontend functions, and I disable ACF on the frontend. I noticed that even when no ACF functions were used on the frontend, ACF was responsible for most of the frontend load time on large sites with lots of content. Not sure why, but this was an easy fix.

  12. Hi Bill,

    Does a CSS version of this concept exist? I’m a designer who “small d” develops and I have to say, I think the way styles.css is organized is abhorrent. I’ve been using style sheets in print and publication design via InDesign and Quark Xpress for 20 years. In that amount of time, while much has changed in how our tools work, the essential best practices for creating organized, clean and manageable stylesheets has mostly stayed the same. I understand how the cascade , nesting and specificity works but i feel that stylesheets would be easier to follow and manage if the toc was consolidated and broken out into individual files by context. The neverending traversing up and down the file along with duplication issues and all sorts of disarray drives me nuts. And this is coming from a man who likes to work efficiently. Any thoughts?

    1. Yes, what you’re describing is SASS. See SASS Basics and this article that describes how to structure a SASS project. Key benefits are:

      1. Break the stylesheet up into multiple discreet units (“partials”)
      2. Can create multiple stylesheets from the partials. Here’s what my main.scss looks like (used on frontend of site) and my editor-style.scss looks like (used for backend editor).
      3. Since development files (.scss) are separate from production files (.css), you can minify the stylesheet automatically as its compiled.
      4. Nesting of styles
      5. Variables. Here’s an example of the base.scss in a project I’m working on now.
      6. Mixins, which are like CSS functions. For instance, when I need to add clearfix to an element, I add `@include clearfix;`.

      Take a look at CodeKit (Mac only) or Prepos (Mac/Windows/Linux). I use CodeKit for processing my SCSS and JS files.

      1. That’s great. Just the impetus I need to dive into SASS, which I’ve been resisting. I think one of the reasons I’ve been resisting is because I’ve been thinking that I need to start completely from scratch. Is it possible to transition into SASS on an existing site without too much disruption?

        thanks for the insights, Bill

        1. Yes, the transition can be as simple as copying your entire style.css file into style.scss (or whatever you want to call it).

          It took me about 5 minutes to transition a site recently to SASS. The original stylesheet was broken down into logical sections, so I made each section a file in the “partials” directory. I then created a main.scss that included all those partials in the order they originally appeared.

Leave a comment