Blog

Sharing WordPress tips and tricks as I find them

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, and shortcodes.

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. That’s the base plugin I now use. 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.

My base child theme used to have all these in the theme. Over the past few months I’ve been moving them to a core functionality plugin on each project, but it’s about time I finally update the base child theme and pull the functionality out into its own plugin.

For added safety, I use a “must use” plugin rather than a standard plugin. Must Use plugins (mu-plugins), are plugins that cannot be disabled. I like to put my core functionality in these so that a client can’t accidentally disable it and break their site. Must Use plugins go in /wp-content/mu-plugins (you’ll need to create that directory if it doesn’t already exist).

Update: I no longer use must use plugins for core functionality. I just create them as normal plugins now. Here’s why:

  1. Managed hosts like WPEngine and Synthesis use the mu-plugins directory for their host-specific plugins. This makes migration a pain since you need to merge your mu-plugins with their mu-plugins.
  2. Likewise, I now use mu-plugins for code/plugins I only want in development, not in production.I have Registered Users Only in mu-plugins along with some code specific to my dev environment.
  3. Clients and other developers don’t know much about mu-plugins. I’ve had many past clients contact me saying they hired someone but he couldn’t find where we registered post types.

23 Comments

  1. I’ve been doing that for a while. I like to register custom post types and taxonomies in a mu-plugins file so it can’t be accidentally disabled.
    http://justintadlock.com/archives/2011/02/02/creating-a-custom-functions-plugin-for-end-users

    • Bill Erickson says:

      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.

  2. Ha. Just ignore my last comments. I just saw this post. :) Thanks

  3. Doak Heggeness says:

    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!

    • Bill Erickson says:

      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.

  4. 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’);
    ?

    • Bill Erickson says:

      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

  5. THANK YOU for sharing this!! I’m just learning to clean up my functions files and this is going to help A LOT!!

  6. 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.

  7. Jon Breitenbucher says:

    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.

    • Bill Erickson says:

      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 :)

      • Jon Breitenbucher says:

        That is kind of what I concluded from my investigations.

        I maintain four network installs. All for the same university. :(

  8. 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.

  9. Richard Buff says:

    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?

    • Bill Erickson says:

      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.

  10. 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).

    • Bill Erickson says:

      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.

  11. 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

    • Bill Erickson says:

      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.

Join the Conversation

If you'd like to include code in your post, please post it to http://gist.github.com and include a link.