Why this sites lives – the story of locate_template

One day at a WordCamp someone asked a core developer why proper theme inheritance is not possible in WordPress and said that the community would love it. My first WordCamp and I was a bit flashed because days before I found out that WordPress can do it – very clean and simple. First I hoped that theme inheritance find its way in every theme and now I share all goodies I find in the core.

Let me show you old but gold features

“Times out, no more questions please.”, said the core developer and my “But WordPress can…” drowned in applause. So outside I told a few people that it is possible by only replacing one often used function with another. They were impressed, so I tweeted about my blog post on codebook.cc (now it can be found here) which explained it a bit more. Some likes, some retweet and that’s all for the weekend.

This can’t be. As a developer I was a bit upset and wonder what kind of persons theme developer are. Thousands words passed by from lazy, over uncaring to creature of habit. And then I found out the real problem: Someone just has to show that it is there and how it works.

Now it is one WordCamp later where I was the speaker in front of the crowd with my own time limit. Everyone was listening how theme inheritance works and one fellow said:

“But… that is what everyone wants!”

Thanks for that! I keep on spreading and nagging until every theme developer does it. “Yee, so true but no one does – everyone copies the same bad code.”, was our final statement and so I continue to nag theme developer with it until the better and good snippets establish themselves as a new modern standard.

New modern theme inheritance

It was Christmas 2008 when WordPress gave the world this magic function: locate_template. Guess what, they announced it as the solution for theme inheritance:

Retrieve the name of the highest priority template file that exists.

Searches in the STYLESHEETPATH before TEMPLATEPATH and wp-includes/theme-compat so that themes which inherit from a parent theme can just overload one file.

There is nothing more to say. Just a few examples to understand this witchcraft. I like to do this with a minimal folder structure of an extensible parent theme and the extending child theme:

  • parent-theme/
    • style.css
    • functions.php
    • inc/
      • bar.php (contains one shortcode)
      • baz.php (contains one widget)
      • qux.php (contains one template)

According to the single-purpose-principle each feature has its own file. This will become handy later on so please write your theme with a lot of files. Thank you in advance!

Todays pain of extending a parent-theme

Now imagine a customer that wants just one widget (baz.php) replaced. How to solve that? Nowadays you would copy the whole functions.php into your child-theme, removing one line and replace it by another:

require_once get_template_directory() . '/inc/bar.php;

// require_once get_template_directory() . '/inc/baz.php;
require_once get_stylesheet_directory() . '/inc/baz.php;

require_once get_template_directory() . '/inc/qux.php;

When I see such lines today they feel wrong in any way I can imagine. And theme developer might have felt that pain too, especially with every theme update. Then you need to recopy the functions.php and redo all the things because the parent update brought new features or moved just one line. This is bad and I want it eliminated. Let’s be lazy.

Proper theme inheritance in WordPress

Remember the parent structure? There were a lot of files in the include folder and every feature has its own file. The customer asked to just change the behavior of one widget (inc/baz.php). In a perfect world the WordPress developer does not care about the functions.php and just creates the file in his own theme:

  • child-theme/
    • style.css
    • inc/
      • bar.php (with changes)

That’s all. Copied the file, made some changes, done. The next theme update can come, the child theme doesn’t care about it. It only offers the changed widget and everything else is up to the parent theme. New features work as expected without doing anything for it. This is clean and simple theme inheritance / extension.

Snippets for theme inheritance

First of all this code goes straight into the parent theme. When you bought a theme then it needs to bring the following lines. This is why the bigger change in our minds need to happen. The mistake using get_template_directory etc happens before we bought the theme. So please share and demand this change wherever your need it. Link and spread this article with theme developers if you like.

Use locate_template everywhere

First of all we need to get in touch with locate_template and how it should be used in the “functions.php”. Here is the good, the bad and the ugly solution side by side:

require_once locate_template( 'inc/baz.php' ); // good!

// bad: require_once get_stylesheet_directory() . '/inc/baz.php';
// ugly: require_once get_template_directory() . '/inc/baz.php';

Replacing all stylesheet- and template-direcotry functions with the locate_template does the trick. With that change your parent theme comes to live and manages itself whenever it needs a feature:

  1. I, as the parent-theme, need “inc/bar.php”.
  2. Is it in the child-theme? If so then I take that.
  3. Is it in the parent-theme? Should be, so I take it.
  4. If not then I take a last look in “wp-includes/theme-compat”.

One function and your (parent) theme does all the work. Isn’t that nice?

Very dynamic and self-managing theme

At this point everything is said. Thank you that you read all this. At last I like to share a simple snippet with you, that makes your theme even more flexible. Every theme has a structure which might look something like that:

  • style.css
  • functions.php
  • inc/
    • shortcodes/
      • foo.php
    • templates/
      • qux.php
    • widgets/
      • bar.php
      • baz.php

If you are good at writing code then this structure is filled with plenty of files for each feature. The “functions.php” might now contain lots of files including all these features. Well actually it is down to a couple of lines that do the work for you:

<?php

$features = new \RecursiveIteratorIterator(
  new \RecursiveDirectoryIterator( TEMPLATEPATH . '/inc' )
);

foreach ($features as $feature_file) {
  require_once locate_template( $feature_file->getPathname() );
}

I hope you take this immediately into your theme and advertise with this new (but old) kind of inheritance. That would make me very happy!

What the blog is about

Finally, the answer to the whole “About” thing. What this website offers you:

  • Snippets that bring modern solutions to old problems.
  • Everything good and wrong about upcoming WordPress.
  • Insights in the core to understand WordPress a bit better.
  • Small tutorials for frameworks you didn’t know that they are always there.

It always has the aim to solve problems only by using core functionality. So no uber plugin and no fancy theme. Just raw WordPress as we love it.

Edit: I just shared this with Sarah Gooding from wptavern.com because she is really great at writing blog posts. Not like me, the computer scientist that scratches words together and almost randomly spills them out with the attempt for a human-readable blog post 😀 So I wonder what other blogger think about it and like to suggest.