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 theafter_setup_themeaction 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()andbrowncoats_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.
Great writeup, Justin!
Out of curiosity: why no
if ( ! function_exists( 'mytheme_setup_theme' ) ) {}wrapper around the Parent Theme’smytheme_setup_theme()function, for direct override by Child Themes?Personally, I hate pluggable functions. Something about them has always felt odd to me. Hooks seem so much smarter and forward-compatible. Plus, you never know when a parent theme might add something new that you’d be overwriting.
I agree. Hooks are much useful. Besides, the problem with plugable function is they are now obsolete.
Another GREAT quality article Justin!
Got to say it was well worth the read, and thanks for that new little bit of knowledge. Maybe I’ll get round to creating a (Child) Theme or that in 2011, we’ll see what happens?
Let me know when you do. I’ll be happy to look over your
functions.php.That’s an offer I can’t refuse!
Good write-up… I tend to just add stuff at the bottom quite often when I’m rebuilding something… Just cleaned up my personal site’s functions file and I like that setup… reads better and overall is much better.
I too just add stuff to the file, especially when I’m doing personal projects. I always remind myself to go back in and do some cleanup though.
My biggest issue is with sidebars, menus, and things such as that just being registered without being added to a hook. You can’t figure out when to unregister things via a child theme.
I really like your theme, my station is to use your theme, thank you very much to share
Cool. It’s always nice to see what my themes look like when used in other languages.
Thank you. Thank you. Thank you. and Thank you. 1 for each of the 4 tips.
I’ve been realizing some of my past errors recently, but the prefixes and priorities really make more sense now. Your tutorials are priceless… well, very valuable at least ; )
Thanks as always.
Glad I could be of some help. Those four tips are just common mistakes I see nearly every day, so I assumed some people could use a little help there.
Show me your functions.php and I’ll tell you who you are
Thanks Justin for great article! I’ll start to clean my themes today.
Even though I’m not building themes anymore, I’m always mucking around in the functions.php files of various themes to do add custimizations or one sort or he other.
Your write has just helped me understand where and how I should be adding my own functions:)
Thanks Justin, glad to see your still writing!
Geez, I guess I need more coffee…sorry for the spelling above :/
Thanks Justin for this great tip. I’m always excited to read new post from your blog. I know something useful will come out from you! Thanks again!
Great write-up, Justin.
I’ve been recently looking into the code of a couple of the so-called premium themes. I felt shocked when I saw how many familiar snippets from the internet were pasted awkwardly into the
functions.phpfile.Post thumbnails function was around for more than a year and many leading theme developers still use
timthumb.phpto resize images and, ironically, they still tell users to insert image URLs in the custom fields when WordPress has post feature image functionality. Maybe these theme developers are only interested to gain fame and fortune without giving much care the quality of their codes.Erm… do you mean “
10is the default, so it is NOT actually shown in the code”?Some
premiumcommercial theme authors are the worst offenders when it comes to sticking every piece of code they can find into a functions file. *cough* – Theme Forest – *cough*.Thanks for catching my missing word. Updated the post.
Thanks Justin. I have never go through the function files in detailed. But through this post it’s really very easy to understand about them. Great piece of work here and hope you will recommend some more good stuff. Especially the code’s gives an idea how to handle such a situation.
I think the problem is that we don’t have enough tutorial/guides like this one. When theme developers have more guides like this one, they will code their themes properly.
I think that’s a major issue too. Hence, this series of tutorials. I’m hoping to help push more theme developers on the right path.
Rami, i cannot agree more with you.
Seriously WP has to give proper guidelines on how to use WP for theme and plug-in developers to produce correct code.
At the moment it is a jungle where one has to spend hours or days to find things.
Seriously, WP core developers cannot claim that people are able to read their minds to understand how to code themes and plug-ins without telling how to use this WP application.
Would you recommend to “always” specify the priority number when using hooks? I’ve never run into a case where I’ve had to specify the priority and would like to know what would be the best practice.
10is the default priority, so any time you don’t set it, it’ll be10. I would only recommend changing this when you have a specific reason for changing it. There’s no reason to set it if you’re not changing it unless you just feel it is more organized or something like that.I prefer to write the hook below the function i.e:
Which way is better ? I do it because I fear that someday the
add_actionfunction will check if the callback is a function.What you mean is that you prefer to add the action after the function has been created. I prefer the opposite way because it seems more organized to me. Since there’s only one example of this in the above tutorial, it’s hardly worth giving much thought to. All other actions/filters added would go in your setup function anyway.
Even if
add_action()ran afunction_exists()call, the function would still exist, despite being created later in the file.Ok thanks for the hint…
Other things every theme/plugin author should know/do:
http://wordpress.stackexchange.com/questions/715/
And yes: (Imo) Everything should be hooked or filtered in wp.
Many good suggestions there that apply to themes. Thanks for posting the link.
that is great thanks Justin
Another GREAT quality article Justin!
My BIG request: can you publish some tuts on:
1. Creating very first real-life plugin from scratch.
2. Creating a simple template from very scratch.
..both using high-top coding standards and practices with all theme /plugin files.
HUGE THANKS!
1) That’s what my book is for.
2) Do you mean theme? Or, is there a specific type of template you’re referring to?
1. Already pre-ordered your book. This is going to be awesome.
2. I meant a general wp theme, maybe web studio theme, but with custom post types+taxonomies and custom page templates (such as portfolio page, full-width page, contact and gallery pages) on board.
Looking forward to it.
Great tutorial.Really simple to understand.
When developing some more complex custom themes, I like to split out groups of custom functions and classes used in functions.php to several include files located in a theme subfolder. Just like the hybrid and your other themes do it.
For example, I often have a bunch of utility functions, then the theme options and admin stuff, etc… splitting them out allows me to reuse them easily in the next project/theme.
I highly recommend splitting stuff up once themes start getting a little more advanced. It’s cleaner and much more organized. I started to mention this in the article, but I wanted to cover the basics first.
Awesome! Tanks a lot
first time reader and i’ve already gobbled up about 4 articles, gonna grab a copy of your book in a few days too.
thanks for the great info and clarity.
i especially love reading about cleaning up code, and only very recently discovered wp hooks after reading sitepoints wordpress book
Thank you for this. Exactly what I needed to sort my code
Question: would adding
load_theme_textdomain(‘my-theme’, TEMPLATEPATH . ‘/languages’);
be appropriate in the same function?
This post is seriously so valuable. I can’t thank you enough for taking the time to go into so munch detail about including functions in our themes.
Understanding how child themes are related to the parent themes is the most important info I got today.
Thanks.
Just to echo all the previous comments and thank you for taking the time to put articles like this together.
This sort of info should really be in the official docs. I look up individual functions all the time in the codex and in the example code given, I don’t recall seeing the example wrapped in a function and wired up with a hook, or they don’t mention which functionality should be matched with which hook.
This encourages bad development practices without developers realising that they are not doing things the right way.
Hey! First of all, thanks for an awesome post. Truly moving.
I’m trying to get my comments styling function inside an add action line. What hook do you think it would be appropriate to put it into? Should it be on the same ‘after_setup_theme’ or is there a better suit?
Thank for a nice tutorial on functions.php. I am trying to clean my header via remove_action( ‘wp_head’, ‘parent_post_rel_link’, 10, 0 ); Should I use After_setup_theme hook for that? Thank you in advance.
As a newbie to Wordpress, I learned a lot just from reading this post. I recently developed a small site that relies a lot on Gravity Forms and their user registration add on. Your members plugin is their go-to solution for solid content management. Gravity Forms is great and your knowledge of Wordpress is clear from your plugins and writing.
I only wish that you had made the login widget that comes with “members” so that it would enable “register or login” for the unregistered or un-logged in user and change to “logout” when a registered user is logged in. In fact the whole user registration and login UX of wordpress could benefit from your attention. Thanks for your good work either way. It’s much appreciated.