A Newbie’s Guide to WordPress Hooks and Functions

When people start wanting to customize WordPress, specifically a theme like Thematic, or a plugin like WooCommerce, I always see questions like:

How do I add “something”, “somewhere”?

or

How do I remove “something” from “somewhere”?

or

How do I change “something”?

At first it is easy to think that adding a div to the #header is different from adding a menu to the #footer, but once you understand how filters and action hooks work, you’ll see these questions really all follow the same pattern. You just need to learn how to speak WordPress! Be patient with yourself, because you literally are learning a new language… especially if you aren’t already familiar with PHP.  I’ll be using examples for working with the [theme-link] but you don’t understanding hooks and functions and eventually filters will be handy in any WordPress project.  Let’s start…

What the heck is an Action Hook

Action hooks look like this:

do_action('this_is_the_action_hook_name');

In a plugin such as WooCommerce, if you investigate in the templates folder you will find all sorts of action hooks. The WooCommerce templates are extremely well-documented and tell you right there which functions are hooked into that action hook and in what order. In the theme, Thematic most of these are buried in the library/extensions folder.  In fact, in the actual templates (like index.php, category.php etc) you will see hooks that look more like:

// action hook for placing content above the index loop
thematic_above_indexloop();

But if you go searching for the definition of that function you will find that it is in content-extensions.php

/**
 * Register action hook: thematic_above_indexloop
 *
 * Located in index.php
 * Just before the loop
 */
function thematic_above_indexloop() {
  do_action('thematic_above_indexloop');
} // end thematic_above_indexloop

Now an action hook is sort of like a parking spot. Some are empty, some have cars on them. you can move the cars around, but the spots themselves stay put. When wordpress gets to an action hook, it will run all the functions that are attached to that particular hook. If it gets to a parking spot and finds a car, it will run that car. If not, then it will continue on to the next hook/space.

How To Add Any Function to any Hook

A completely fictitious example:

function function_you_want_to_add(){
echo "I heart bacon!";
}
add_action('destination_hook','function_you_want_to_add', $priority, $args );

The add_action line is doing the heavy lifting here, and always takes this same “form”…. it sort of reads like this in english:

Add the function called ‘function_you_want_to_add’ to the hook called ‘destination_hook’ in the order of $priority with some optional extra arguments called $args.

You can read all about add_action in the WordPress Codex (hint: there is a TON of info there, but I understand it can be overwhelming at first).

The $priority is always a number. It is like a traffic cop in the parking lot, or maybe just an orange cone. if more than 1 function wants to be on a particular hook the priority decides which goes first. If 2 cars wanted to be in the same spot, the one with the lower number priority would get ground level parking and the one with the higher priority would be stacked on top. Yay 3-d parking! Sorry, prepare yourself we are going to beat this metaphor to death. The default priority is 10, so if you don’t need to change that you don’t even need to define it in your add_action line.

Some hooks pass additional variables to the functions that operate on them, but this is pretty advanced so for an introductory primer we will ignore it.

Now, a practical example:

function function_you_want_to_add(){
echo "I heart bacon!";
}
add_action('thematic_above_indexloop','function_you_want_to_add');

If you add the practice example to your child theme’s functions.php you will see “I heart bacon!” appear on your blog page. Now leave that there and add the following just underneath it in your functions.php.

function kia_another_function(){
echo "Guacamole makes me happy!“;
}
add_action('thematic_above_indexloop','kia_another_function', 5);

Notice the priority number is 5. This means it has a lower priority number than the first function, which is 10 by default since we didn’t specify anything. When you reload your theme you should now see Guacamole makes me happy! on the blog index above the line about loving bacon. Bacon and guacamole together. It must be code heaven.

How to Remove Something From a Hook

removing stuff works a bit differently:

function remove_stuff(){
remove_action('hook_location','function_you_want_to_remove',$priority );
}
add_action('init','remove_stuff');

In english this sort of translates to:

When WordPress runs the init hook, please remove the function called “function_you_want_to_remove” that is located on the hook called “hook_location” with a priority of $priority.

init is just a WordPress hook. in fact, it is the one of the earliest hooks that run when WP starts whirring… it is like priority parking. You can see most all of the hooks that run in the WordPress process again at the Codex: Action Hooks  To remove something that had a specific priority originally, you must remove_action it with the same priority.  A good practical example would be removing the Thematic blog title.

function remove_thematic_header(){
remove_action('thematic_header','thematic_blogtitle', 3);
}
add_action('init','remove_thematic_header');

Paste the above into your functions.php, reload your child theme and poof the blog title is gonzo!

Moving the #access menu is another practical example, that combines adding and removing functions.  I’ll include it here because I see this question asked all the time.

function remove_thematic_header(){
remove_action('thematic_header','thematic_access', 9);
}
add_action('init','remove_thematic_header');
add_action('thematic_aboveheader','thematic_access');

Note that we don’t have to define thematic_access, because it already is defined by thematic. We can simply add_action it to a new parking spot.

Overrides R’ Us

Thematic has a bunch of functions built in that if you define them, they automagically replace the function thematic was going to add to a specific hook, with your custom function.  In WordPress parlance, this is called a pluggable function.  Many thematic functions can be overridden by copying a thematic function to your functions.php and altering the function’s prefix from thematic_ to childtheme_override_.  The overrides completely change the car that is parked on a particular parking spot but they don’t change its location.

For instance to override the thematic_blog_description you could put the following in your functions.php

function childtheme_override_blogdescription(){
echo "Evil laugh! Now your blog is only about bacon!";
}

Refresh your theme and you will see the blog description has been taken over by bacon. , which I think is neat.  Note that with pluggable functions you do not need to also call add_action.  Doing so will add the function twice.  Most functions in thematic have this override capability, but not all.  You can browse through the extensions folder (look but don’t touch the parent theme!)

If you see something like:

if ( function_exists('childtheme_override_blogdescription') )

That’s a sign that you can use the override feature.  The full IF statement reads something like:

If you define a child_theme_override function then Thematic will add your custom function to the appropriate hook instead of its own function.

Overrides are significantly more intuitive than filters, but filters can be more elegant: the scalpel instead of a broadsword if you don’t need to change the entire function.  However, this post is crazy long, so I will leave filters for the next part of series.

Additional Resources

To help you know what hooks are available in Thematic, here are 2 visual aids:

http://www.bluemandala.com/thematic/thematic-structure.html

http://visualizing.thematic4you.com

Additional Help

I’ve tried to make this as beginner-friendly as possible, but I’ve been doing this for a few years now and so it makes total sense to me. Please let me know in the comments if something about this tutorial is not clear so that I can make it better.

Also, I don’t have time to respond to specific support requests in the comments. If you have Thematic questions post them at the Thematic Forums or contact me for some premium support.

Absolute PHP Basics for WordPress Newbs

“I’m just a designer. I’m comfortable with CSS but PHP scares me.” Yeah ok, well first off, if you are a designer…. instead of banging your head into a wall to learn a coding language, why not hire a developer? Some of my best clients have been designers. It is kind of a win, win. I get to work on pretty sites and you get to do more designing and less stressing. Send me an email and let’s see if I can help.

But if you insist on trying to defy your right-brained designery nature and become more left-brained here are a couple of points that I think will help you as you try to learn both PHP and its sub-dialect of WordPress.

Function Function What’s Your Function

Functions do things. Ever learn about functions in middle school math class? Magic black-boxes where numbers go and come out as something else? Well it is pretty much the same. Let’s start with the simplest function possible, a nice spin off on the classic “hello world”.

[php]
function hello_bacon(){
echo “hello bacon”;
}

hello_bacon(); // prints: hello bacon
[/php]

But not all functions echo out a value because we don’t always want to echo (which is just another way to print something) a value out right away. Sometimes we need to process it more, etc. In that case you’d return a value. Returning a value is just the opposite of echoing a value. It says, don’t print it right now, save it for later.

[php]
function hello_bacon(){
return “hello bacon”;
}

hello_bacon(); // prints: NOTHING! oh hold up!
[/php]

To print it later we’d have to actually echo out the function.

[php]
echo hello_bacon();
[/php]

or

[php]
$hello = hello_bacon();
echo $hello; // prints: hello bacon
[/php]

See what we did there in that second one? We defined a variable, which if you’ll remember from math class is a bit of an amorphous blob that can have any value. Then we set that variable equal to the value returned from the hello_bacon() function.

Getting into Arguments

The hello_bacon() function is obviously super simple. It always returns the same thing. Well that’s not so much fun and sort of defeats the purpose of a function. Remember those magic black boxes? Well now we want to take a variable in, manipulate it and spit it back as something new and shiny. We send variables into functions as arguments to that function.

[php]
function favorite_food($food){
echo ‘My favorite food is ‘ . $food;
}

favorite_food(); //prints: My favorite food is <–didn’t pass an argument so $food is empty, and I’m hungry.
favorite_food(‘guacamole’); //prints: My favorite food is guacamole
[/php]

As you can see above, the favorite_food() function accepts 1 argument. Inside of the favorite_food() function this argument will be referred to by the variable $food. This sort of touches on a concept that we’ll get into in a bit, called variable scope. But for now remember that $food does not exist outside the favorite_food() function.

[php]
favorite_food(‘guacamole’); //still prints: My favorite food is guacamole
echo $food; //nothing doing
[/php]

If you need to ensure that you never get an empty value for “My favorite food is ____” then you can give an argument a default. If you don’t pass an argument when calling a function it will simply use the default. Note below that ‘bacon’ is the default value of the $food variable.

[php]
function favorite_food($food = ‘bacon’){
echo ‘My favorite food is ‘ . $food;
}

favorite_food(); //prints: My favorite food is bacon
favorite_food(‘guacamole’); //prints: My favorite food is guacamole
[/php]

By now you might have noticed that we’ve only been dealing with what are called, ‘string’ variable types…. words or letters essentially. You’ve been seeing me combine strings together with a period (.) in what is called string concatenation. But just like math class, PHP functions work on numbers.

[php]
function double($x){
return $x * 2;
}

$a = 10;
$a = double($a);
echo $a; //prints: 20
[/php]

Variable Scope

Whoa hold up! You just said the argument was called $x, but there you go calling it $a. Yup. Remember when I said it was important to remember that variables (usually) only exist inside the function where they are defined. That is what is called variable scope. In PHP and WordPress you can declare variables as global in scope, meaning $x has the same value everywhere, but by default variables are local in scope, meaning again, they only exist within the functions using them.

I could rewrite the above to be:

[php]
function double($guacamole){
return $guacamole * 2;
}

$bacon = 10;
$bacon = double($bacon);
echo $bacon; //prints: 20
[/php]

I can call the variables anything I want, because the $guacamole in the double() function is not the same as the $bacon outside of it. Remember variables are placeholders. Think of it like the two are playing catch. In the following line:

[php]
$bacon = double($bacon);
[/php]

We are passing a value to the double() function. The function then catches the value as its argument.

[php]
function double($guacamole)
[/php]

Now the variable has a new name, but the same value. In the example the value was 10, that part isn’t any different. Within the function the variable $guacamole now has a value of 10. Then it performs its multiplication and sends back the doubled value. The is the pass back.

[php]
return $guacmole *2;
[/php]

And that brings us back to:

[php]
$bacon = double($bacon);
[/php]

where the variable $bacon catches the return pass, and the variable $bacon is now equal to 20, which we see when we echo $bacon.

So it is like playing catch. If you are out in the yard playing catch with someone who doesn’t speak the same language as you and you toss the ball to your partner, when he catches it, he might call it a beisbol. When he throws it back to you, it is a baseball again, you both just had different words (variables) for it.

This is the official PHP manual that might help explain things if my metaphors made it clear as mud.

http://php.net/manual/en/language.variables.scope.php

In Summary

We covered functions, function arguments, string variables, numeric variables and variable scope. There is quite a bit more, but I already feel like this is a lot actually and hopefully you are well on your way to programming hell… I mean bliss. Please point out any errors or places where I could be more clear, but keep Thematic and WordPress specific questions for their respective forums. Best of luck.

WordPress Filters Fundamentals

Ok, so you’ve read my previous articles on PHP basics and how to use WordPress action hooks. Now you want to play with the big boys and girls and try your hand at filters. Just a reminder that you are still essentially learning a new language. Be patient with yourself. It took me close to a year to really understand filters, so if I can help you learn it quicker than that I’ll consider this a successful article.

In my discussion of hooks and functions I have described the system of hooks in WordPress as being similar to a parking lot. The hooks are like spaces, the cars are like functions that can be parked anywhere and can be moved around. To expound on this metaphor, (or to beat it to death) I think a filter is similar to changing something about the car while leaving it in the same place. A filter is like a magic function box that takes a value in ( remember I talked about parameters in by Basics tutorial ) do something with it and send it back. So you have a red Porsche on the lot, send it to a filter and it might become a blue Porsche. Or a black pickup truck. Whatever. But it will still be parked in the back, 2 spots from the end.

When browsing WordPress core, themes and plugins, you will be alerted to the availability of a filter by the appearance of the apply_filters() function. In generic terms it will look like so:

It might look like:

or:

or even:

Parameters for the Filters

But I repeat, the big tip off is the apply_filters() function. The apply_filters() function can take an unlimited number of parameters but only the first two are required. 1. The first is the name of the filter. I was very confused early on because the Thematic framework tended to name the filters the same thing as the functions that contained them. And then in the one instance where they were different, I couldn’t get my filter to work for anything. I swore and threw things, cried and probably shaved a few days off my life from the stress. Turns out their sharing names was a convenience factor that makes a lot more sense to me now. So, just remember that first parameter is the filter’s name. 2. This is an important one, because this parameter is the variable that your function will receive. This is the value we’re going to change. This is the red car that we will turn blue. 3. This it the priority. Just like with adding functions to hooks, this controls the order that filter functions will be applied should there be more than one. The default is 10, so if you need your filter to run before that you’d use a lower number. This is rare, and usually you need to run your filters after others, so you’d want to use a higher number. In fact, until you are sure that you are conflicting with another function you can pretty much just leave it at 10. 4+. These are other variables that might give you some useful information for manipulating the variable getting filtered. Remember we talked about scope in the PHP Basics. Instead of declaring these globally and hoping they arrive intact, WordPress will send your filtered variable along with some friends.

A Filter with Training Wheels

In super generic terms let’s take a look at the basic set up for filtering.

The structure is almost exactly the same as that for add_action(). In reality, we are adding an action, just of a slightly different type: one that modifies a specific variable’s value. One thing to note here, is the number 2. This is the number of parameters that you are passing into the function. You’ll always pass 1 variable ( ie. the variable that you are filtering ) and in this case you wouldn’t even need to declare it. That’s the default value, just as 10 is the default value for #priority. However, some filters provide access to other variables (like our fake $other_arg), and if you want to use them in your filter function then you have to name them inside the parentheses and then write the correct number at the end of the add_filter() statement.

If you have 2 parameters in the function, but don’t have the number 2 at the end of add_filter() you will get White Screen of Death. If you have the number 2, but don’t declare two parameters, guess what, you will also get WSOD. So make sure your parameters match up. And you absolutely, must, sans doute, return a value. If you do not, that is essentially the same as returning a null string. If you echo something here, it will likely not appear where you expect it, so don’t. RETURN, RETURN, RETURN.

Remember in my PHP basics I talked about two functions playing catch. The return statement, is you throwing your modified version of the variable back to the apply_filters() function so that WordPress can continue on its merry way, but using your value now.

You’re a Real Boy Now, Pinocchio.

A Real Filter If you’ve managed to read all this, then… well… Bless you. I want to end on a real filter that you can drop into your theme’s functions.php and actually see a working result.

Not too shockingly I am using Bacon in my testing code. If this bothers you… well, its not real bacon and you may use whatever you wish in your own tests. WordPress has a filter called the_title() that lets you modify the title of every post! As written above it will literally add BACON everywhere the_title() is called. Bacon everywhere, all the time has its appeal, sure, but I will whet your appetite with some neato WordPress conditional logic that will only add Bacon to the titles in the main loop, and only on the front-end.

Conclusion

I hope that helps things make more sense. Remember, THIS IS HARD!! Do not be discouraged if you don’t get it right away. I cannot provide specific support in the comments ( Hire Me, instead! but do let me know if there are places where I could be more clear.