Plugin or Theme? Where Does My Code Go?

Where do you put your code? It’s a problem with every language, platform and framework, and WordPress is no exception. If you’ve worked on a WordPress site of any size, you’ve probably struggled with the same thing I have:

Does this code go in a plugin or the theme?

Some background

I’ve dabbled in a wide spectrum of WordPress development, ranging from simple theme modifications to big honkin’ plugins powering high-traffic sites. When I moved to more complex WP sites, I ran into new challenges I never saw in simple plugins and theme modifications. If you suffer from developer scruples like I do, you run a risk of falling into despair trying to cleanly solve these problems.

In fact, I don’t think there are complete, satisfying answers to some WP development problems. Inspired by the list of computer science problems thought unsolvable in polynomial time, I call this set of problems “WP Complete”.

The first WP Complete problem: plugin or theme?

Sometimes, it’s obvious. From this WordPress StackExchange question, the insightful Chip Bennett lays a foundation for answering the question:

Is the functionality related to presentation of content, or with generation/management of content, or of the site, or of the user identity? If the functionality is not related specifically to presentation of content, then it is squarely within Plugin Territory.

I wholeheartedly agree, and this is easy to discern when there is a core hook that does what you’re looking for. But what if that hook doesn’t exist?

On a recent project, I implemented a front-end login system for a client – a way for non-admin users to login using a modal on the homepage of the site. I needed to add a “login” link to the header of the site: some basic HTML, CSS and JS. The login link is loosely related to the presentation of the content, but the login functionality is clearly part of the plugin. Disabling the plugin should hide the header link.

The solution was to use a hook. Alas, there was no hook in the theme I could use to place the HTML in the right spot. Here’s what the header.php file looked like:

No hook? No problem! I added it myself:

Awesome! A clean and durable solution that will survive plugin deactivation or (to some degree) theme changing. But there are caveats: This only works if you have full control over the theme.

In my case, the theme was completely custom and in my control. If your theme is not custom and has regular updates, watch out: your hook could be overwritten on update!

Child themes

This is a good time to talk about child themes. If you need to make stylistic additions to a parent theme, child themes are a great option. For someone unfamiliar with coding who wants to tinker with their theme, child themes are the way to go. For code changes & adding HTML, child themes are…meh.

CSS changes are cascading, meaning your child theme’s style.css file will add to the parent theme. But if you need to add a hook to header.php like the example above, your child theme needs to completely overwrite the header.php file. When the parent theme updates, you run a risk of having outdated code in your child theme’s header.php.

The big issue

The underlying issue that makes this an unsolvable problem is that the theme controls all display, and there are no standards for theme hooks. There is an effort to standardize theme hooks, but this relies on a consistent implementation from a whole ‘lotta theme developers – something that will be slow to adopt if it gains traction at all.

I don’t know much about Joomla! development, but I did a WordPress project for an experienced Joomla! developer, and when I tried to explain this plugin vs. theme display problem to him, he was utterly baffled. I’m guessing Joomla! has some consistent way of adding to templates that WordPress is lacking.

Another use case

The problem manifests itself when you add a Custom Post Type via a plugin. How do you display that CPT on the front end of the site? Assuming the CPT needs a special template, you have to add that template to the theme, even if the CPT is completely dependent on the plugin being activated.

This is for a couple of reasons:

1. The template hierarchy only scans the theme for relevant templates.
2. The theme can (and 99% of the time, does) use a unique HTML structure that has to be mimicked (copy-pasted, basically) into any new templates.

Meta = more problems

When I add meta information to posts or users, I like to put the meta keys into constants to prevent typos and for readability. Typically, this looks like so:

My_Plugin_Meta is defined in a plugin. This becomes a problem when the theme needs to use the meta keys. In the theme, this line becomes an issue:

$meta_value = get_post_meta( $post_id, My_Plugin_Meta::MyMetaKeyOne, true );

If/when the plugin is deactivated, the theme will crash here. There are a couple of ways to solve this, neither of which is ideal:

1. Don’t use the constants. The theme would use strings to access meta information:

This neutralizes the whole point of using constants, but it allows the theme to continue working without the plugin.

2. Check for the class before getting the meta value:

I use approach #1 with a tinge of disappointment. My attempts to avoid retyping meta keys are foiled.

(Have a better approach? Please share it in the comments)

What’s the Answer?

I wish I knew. Right now, the answer is it depends. It depends on:

  • Can you modify the theme easily?
  • Do you “own” the entire codebase, or are you just making modifications?
  • Is there a chance that plugins will be deactivated or themes switched?

If you’ve faced this problem and have any suggestions, I’d love to hear them in the comments. I’m still trying to solve this one!

 

 

Enjoyed this article?Tweet about this on TwitterShare on FacebookShare on Reddit

I use Hiveage for all my freelancing work. The price & features are perfect for solo freelancers and small teams. Use coupon CERTAINL10 to get 10% off. I am an affiliate of Hiveage, but only because I love their software.

2 comments

    • Andy Adams says:

      MU is an interesting angle. I admittedly don’t have much experience, but it would still be possible to delete the MU plugin. Harder, but if you can delete it then you have a similar problem.

Leave a Reply

Your email address will not be published. Required fields are marked *