WordPress theme function files

One of my biggest complaints about a lot of WordPress themes is their poorly-coded functions.php files. This is a file that all WordPress themes use, but so many of them could be coded much better.

The two major issues I see the most with themes’ functions files are:

  • Code placed randomly in the file.
  • Not using the hooks WordPress provides.

By following this tutorial, you’ll learn how to create beautifully-coded, logically-sound function files for your themes. You’ll also learn how to overcome a major “issue” present with the way WordPress loads parent/child theme functions files.

What is a functions file?

In WordPress, themes can have a file called functions.php, which loads PHP functions for the theme. It behaves in much the same way as a plugin. Plus, WordPress automatically loads this file when a theme is active. Both the parent theme and child theme functions.php files are loaded when using a parent/child theme setup.

The only limits to what can be done with a functions file are your imagination and PHP skills.

Even though the functions file works like a plugin, it's not a plugin. There's definitely a fine line between what should be in a plugin or a theme sometimes, but I encourage theme authors to try to limit a theme functions file to functionality specific to the theme itself.

Creating a theme functions file

If you haven’t already done so, create a blank functions.php file within your theme. This is the file all of your custom code will go into.

Once you’ve created the file, drop this code into it:

<?php
/* Custom code goes below this line. */

/* Custom code goes above this line. */
?>

Prefixing function names

Before moving forward, there’s one important rule you need to remember: Prefix everything.

That’s a fairly simple rule to follow. I still see tons of themes that get this wrong, so let’s look at an example. Suppose you had a custom theme function called comment_output() and it looked something like this:

function comment_output() {
	/* Example code. */
}

That’s dangerous territory. If WordPress or a plugin that’s not following this rule adds a new function in the future called comment_output(), your users will get a big, fat fatal error. This isn’t something you want to happen.

Suppose your theme name was Browncoats. You should prefix all custom functions with browncoats_. So, the function above would now look like:

function browncoats_comment_output() {
	/* Example code. */
}

That’s an extremely simple change and will most likely never cause you any headaches in the future.

This rule isn't just limited to function names. Global variables, constants, and classes should always be unique, so make sure these are prefixed as well.

Creating a theme setup function

We’re going to kill a few birds with one stone here.

  • Properly execute functionality on a WordPress hook.
  • Allow child themes to easily overwrite functionality.
  • Better organize the functions file.

WordPress has an action hook called after_setup_theme. This hook is fired once both the parent and child themes’ functions files are loaded. It’s a great hook for setting up your theme. Even WordPress’ built-in theme TwentyTen uses this (finally glad to see something like this in the default WordPress theme).

add_action( 'after_setup_theme', 'browncoats_theme_setup' );

function browncoats_theme_setup() {
	/* Add filters, actions, and theme-supported features. */
}

By taking this simple step, you’ve started the process of cleaning up your theme’s functions.php file. This function should be used to do a few things:

  • Add custom actions to action hooks.
  • Add custom filters to filter hooks.
  • Register support for theme-supported features.

So, let’s look at a better example of a theme’s functions.php file.

<?php

add_action( 'after_setup_theme', 'browncoats_theme_setup' );

function browncoats_theme_setup() {

	/* Add theme-supported features. */
	add_theme_support( 'automatic-feed-links' );

	/* Add custom actions. */
	add_action( 'widgets_init', 'browncoats_register_sidebars' );

	/* Add custom filters. */
	add_filter( 'the_content', 'browncoats_highlight_words' );
}

function browncoats_register_sidebars() {
	/* Example. */
}

function browncoats_highlight_words( $content ) {
	return $content;
}

?>

The code above is fairly simple. Three things are happening:

  • Adds the theme setup function browncoats_theme_setup() to the after_setup_theme action hook.
  • The theme setup function registers support for theme-supported features, adds an action to an action hook, and adds a filter to a filter hook.
  • The browncoats_register_sidebars() and browncoats_highlight_words() functions are executed on specific hooks.

Creating a child theme functions file

One of my gripes (sometimes) is that WordPress loads a child theme’s functions.php file before its parent theme functions.php file. This is done so that a parent theme can make pluggable functions. But, it’s a pain for many people because they’re trying to remove filters and actions added by the parent theme.

There’s a solution to this problem though. Notice that you created a [parent] theme setup function and hooked it to after_setup_theme with a priority of 10 in the previous section (10 is the default, so it’s not actually shown in the code).

add_action( 'after_setup_theme', 'browncoats_theme_setup' );

What this does is hold off the parent theme functionality from executing until the after_setup_theme action hook is fired. This allows child themes to know exactly when the parent theme executes code.

Suppose you have a child theme called Purple Bellies. Your theme setup function would look like the below:

purple_bellies_theme_setup() {
	/* Add filters, actions, and theme-supported features. */
}

You know that you should fire it on the after_setup_theme action hook, but when to add it is the question. If you want your child theme to fire before the parent theme, you’d use a priority of 9:

add_action( 'after_setup_theme', 'purple_bellies_theme_setup', 9 );

Or, if you wanted to fire it after the parent theme, you’d use a priority of 11:

add_action( 'after_setup_theme', 'purple_bellies_theme_setup', 11 );

Some tips to a better functions file

The following are some things that you should definitely keep in mind when building your functions file.

Tip #1: Prefix everything

I know I covered this earlier, but I thought it worth mentioning again. Make sure to always prefix your custom functions with a unique identifier. I’ve been using browncoats_ throughout this tutorial because my theme’s name is Browncoats.

Tip #2: Hook everything

WordPress provides hooks that allow developers to execute functionality at certain points within the WordPress flow. I won’t cover how hooks work here, but if you don’t know how to use hooks or even what they are, you should not be adding code to a theme functions file. Just dropping random snippets of code you’ve found from around the Web into this file is not something you should do.

All code within your functions.php file should be wrapped within a custom function. This function should then be added to an action or filter hook.

By adding everything from a hook, your functions file becomes much more organized and allows users to remove things using the remove_action() or remove_filter() functions. It also makes sure that things are loaded at their proper point in the WordPress flow.

Tip #3: Keep functions simple

Sometimes, I see themes with extremely complex functions that do multiple things. There’s nothing wrong with having a function that performs something complex, but you shouldn’t make it complex by having the function perform more than a single function. Use multiple functions for multiple operations.

Tip #4: Use WordPress functions where possible

Always look for a solution in the core WordPress code before writing your own code. I’ve seen too many functions written that could’ve been done with an equivalent WordPress function in themes. There are two major benefits to doing this:

  • You have less code to maintain and debug.
  • Many plugins rely on hooks that these WordPress functions provide. When you don't use the appropriate function, it breaks plugins. Then, plugin authors get blamed for something a theme got wrong.

An example functions file

Let’s revisit our Browncoats theme and put together a sample functions.php file that fits in with the theme review guidelines, uses hooks, and implements some common functionality found within themes.

Take note how everything is organized within the theme setup function and all code is wrapped into separate functions.

<?php

add_action( 'after_setup_theme', 'browncoats_theme_setup' );

function browncoats_theme_setup() {
	global $content_width;

	/* Set the $content_width for things such as video embeds. */
	if ( !isset( $content_width ) )
		$content_width = 600;

	/* Add theme support for automatic feed links. */
	add_theme_support( 'automatic-feed-links' );

	/* Add theme support for post thumbnails (featured images). */
	add_theme_support( 'post-thumbnails' );

	/* Add theme support for custom backgrounds. */
	add_custom_background();

	/* Add your nav menus function to the 'init' action hook. */
	add_action( 'init', 'browncoats_register_menus' );

	/* Add your sidebars function to the 'widgets_init' action hook. */
	add_action( 'widgets_init', 'browncoats_register_sidebars' );

	/* Load JavaScript files on the 'wp_enqueue_scripts' action hook. */
	add_action( 'wp_enqueue_scripts', 'browncoats_load_scripts' );
}

function browncoats_register_menus() {
	/* Register nav menus using register_nav_menu() or register_nav_menus() here. */
}

function browncoats_register_sidebars() {
	/* Register dynamic sidebars using register_sidebar() here. */
}

function browncoats_load_scripts() {
	/* Enqueue custom Javascript here using wp_enqueue_script(). */

	/* Load the comment reply JavaScript. */
	if ( is_singular() && get_option( 'thread_comments' ) && comments_open() )
		wp_enqueue_script( 'comment-reply' );
}

?>

Time to clean up those functions files

If I could choose only one thing I’d like to see magically disappear on the WordPress theme repository (and even in many commercial themes) it would be sloppy practices within theme functions.php files. Everything I’ve covered in this tutorial is basic stuff that anyone developing on top of WordPress should be familiar with.

If you’re a theme developer, feel free to ask questions if you’re unsure about anything covered above. I know a lot of theme authors aren’t developers, only getting into WordPress themes because they love design. So, if you have trouble with PHP, hooks, or anything to do with a functions file, the best thing to do is to ask someone for help.