Rethinking template tags in plugins

Some plugins offer their own template tags that the blogger can add to their theme where they’d like to display it. Some may even be loaded with an array of arguments to further customize the options. We’ll stick to a simple myplugin_related_posts() template tag as an example throughout.

Usually, these plugins can’t or aren’t willing to take advantage of hooks, such as appending information to the post content, or widgets. That’s okay, especially so when they also offer those alternatives, but also include a theme template tag.

I want to rethink this process. Some bloggers are weary of modifying templates, some plugins’ instructions are plain dangerous, and some bloggers would love to take advantage of a plugin, but it doesn’t allow much flexibility with its output.

Take this as an example:

// Add this to your theme
myplugin_related_posts();

But, what happens when myplugin is deactivated? That function suddenly no longer exists, and the blog blows up. Of course, most plugin authors realize this, and encourage this instead:

// Add this to your theme
if ( function_exists( 'myplugin_related_posts' ) )
    myplugin_related_posts();

Not bad, but clunky. How can we do this better?

Using Hooks for Template Tags

Dion Hulse blew my mind away when he mentioned this method to me a few months ago. Sure, all developers use hooks on a regular basis, but the ingenuity of using a hook as a template tag was too good to resist.

As an example:

// Add this to your theme
do_action( 'myplugin_related_posts' );

Wow, how cool is that? Look ma, clean code! And no fatal errors! Now all the plugin author needs to do is add their existing template tag to that action:

add_action( 'myplugin_related_posts', 'myplugin_related_posts' );

And, if the plugin author doesn’t provide that, then you can do it yourself in your theme’s functions.php, right next to perhaps other filters and actions that modify or add to the hundreds of template tags built into WordPress.

What’s to stop you from adding arguments?

// Add this to your theme
do_action( 'myplugin_related_posts', array( 'count' => 5 ) );

Or, what’s to stop you from removing, replacing, or adding additional callbacks to the same hook?

If the template tag returns a result and needs to be echoed, you can attach the tag to a filter instead:

echo apply_filters( 'myplugin_get_related_posts', '' );

There are a handful of reasons why I really like this method:

One, it requires no effort for the plugin author to passively support this, as most template tags can already be used as callbacks. To actively support this, they can include an add_action call in their plugin, for the times the hook exists.

They don’t need to require the use of a hook, of course — the widget, template tag, hook, etc., all can be supplied, and the user can choose what to use.

Two, administrators can do this themselves by tying the template tag to a hook on their own. They may need their own wrapper function to support more complex tags, but it’s generally worth it.

Three, if the hook doesn’t exist in the theme, then the plugin’s add_action doesn’t do anything. The converse is that if the callback doesn’t exist, then the action hook doesn’t do anything. No fatal errors.

Four, it encourages plugins and themes to play nice with each other through clean, flexible, and robust methods.

Of course, the template-tag-as-a-callback method is only for those situations where the tag needs to be placed in a particular spot. There’s nothing stopping you from taking the template tag provided by the author and simply leveraging the existing hooks system to append the HTML to the post using the the_content filter.

Leverage the WordPress plugin API and reap the benefits.