52
votes

Where can I find a list of all the WordPress hooks and over-ridable functions (pluggable, scriptable, etc)?

Edit: Plugin is listed here.

2

7 Answers 7

47
votes

@Arlen: As Keith S points out Adam Brown's List of Hooks is the defacto resource of hooks for WordPress. However, it's not perfect:

  • It doesn't show the hooks in order of when they are called,
  • It doesn't provide file name or line number where invoked,
  • It doesn't provide a number of arguments passed,
  • It's not a complete list because some hooks can be called dynamically,
  • And it doesn't show hooks from plugins.

So while Adam's list is a great resource especially for understanding when hooks were historically added it's not nearly as useful as if you were able to instrument the hooks on any given page on your own site.

I've been toying with this idea for a while so your question triggered me to write a plugin called "Instrument Hooks for WordPress." You can find the full source below the screen shot and can you can also download it from gist here.

So here's a screenshot of what the instrumentation looks like:

Screenshot of Instrument Hooks for WordPress Plugin in action

You trigger the instrumentation by using the URL parameter instrument=hooks, i.e.:

http://example.com?instrument=hooks

And as promised, here's the source (or download it here.):

<?php
/*
Plugin Name: Instrument Hooks for WordPress
Description: Instruments Hooks for a Page. Outputs during the Shutdown Hook.
Version: 0.1
Author: Mike Schinkel
Author URI: http://mikeschinkel.com
*/

if ($_GET['instrument']=='hooks') {

    add_action('shutdown','instrument_hooks');
    function instrument_hooks() {
        global $wpdb;
        $hooks = $wpdb->get_results("SELECT * FROM wp_hook_list ORDER BY first_call");
        $html = array();
        $html[] = '<style>#instrumented-hook-list table,#instrumented-hook-list th,#instrumented-hook-list td {border:1px solid gray;padding:2px 5px;}</style>
<div align="center" id="instrumented-hook-list">
    <table>
        <tr>
        <th>First Call</th>
        <th>Hook Name</th>
        <th>Hook Type</th>
        <th>Arg Count</th>
        <th>Called By</th>
        <th>Line #</th>
        <th>File Name</th>
        </tr>';
        foreach($hooks as $hook) {
            $html[] = "<tr>
            <td>{$hook->first_call}</td>
            <td>{$hook->hook_name}</td>
            <td>{$hook->hook_type}</td>
            <td>{$hook->arg_count}</td>
            <td>{$hook->called_by}</td>
            <td>{$hook->line_num}</td>
            <td>{$hook->file_name}</td>
            </tr>";
        }
        $html[] = '</table></div>';
        echo implode("\n",$html);
    }

    add_action('all','record_hook_usage');
    function record_hook_usage($hook){
        global $wpdb;
        static $in_hook = false;
        static $first_call = 1;
        static $doc_root;
        $callstack = debug_backtrace();
        if (!$in_hook) {
            $in_hook = true;
            if ($first_call==1) {
                $doc_root = $_SERVER['DOCUMENT_ROOT'];
                $results = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wp_hook_list'");
                if (count($results)==1) {
                    $wpdb->query("TRUNCATE TABLE wp_hook_list");
                } else {
                    $wpdb->query("CREATE TABLE wp_hook_list (
                    called_by varchar(96) NOT NULL,
                    hook_name varchar(96) NOT NULL,
                    hook_type varchar(15) NOT NULL,
                    first_call int(11) NOT NULL,
                    arg_count tinyint(4) NOT NULL,
                    file_name varchar(128) NOT NULL,
                    line_num smallint NOT NULL,
                    PRIMARY KEY (first_call,hook_name))"
                    );
                }
            }
            $args = func_get_args();
            $arg_count = count($args)-1;
            $hook_type = str_replace('do_','',
                str_replace('apply_filters','filter',
                    str_replace('_ref_array','[]',
                        $callstack[3]['function'])));
            $file_name = str_replace($doc_root,'',$callstack[3]['file']);
            $line_num = $callstack[3]['line'];
            $called_by = $callstack[4]['function'];
            $wpdb->query("INSERT wp_hook_list
                (first_call,called_by,hook_name,hook_type,arg_count,file_name,line_num)
                VALUES ($first_call,'$called_by()','$hook','$hook_type',$arg_count,'$file_name',$line_num)");
            $first_call++;
            $in_hook = false;
        }
    }
}
9
  • I would...it's one of those things that you might only use once or twice, but when you do use it, you thank the stars for it :)
    – Keith S.
    Aug 14, 2010 at 3:09
  • 1
    Mike, that's very cool! But what would you recommend for actually understanding what each filter/action does? is there a file where all of those are listed along with their 'activity'? Thanks!
    – Amit
    Aug 14, 2010 at 13:10
  • 1
    @Amit - Yes, that is the hard question. :) Thanks for asking. Unfortunately, I can't see any way to automate that like I did for listing the hooks above so I don't have a perfect answer for you. Ideally for each hook someone would write a great blog post (or ask a question here which got great answer) and then "Google it" would be your answer. As is, I use a debugging IDE (PhpStorm+XDEBUG, US$49 until Sept 2010) and I set breakpoints and just trace through the executing code. There may be a better way though, and if someone else has thought of it please let us know! Aug 14, 2010 at 22:44
  • 3
    @Mike: Quick question, why do you store that into the database instead of memory or a temporary stream?
    – hakre
    Aug 18, 2010 at 8:31
  • 1
    @hakre - Good question! When I started writing the plugin I envisioned it to collect info about hooks across multiple page loads. After I finished implementing it I realized it would be more useful to do it just fort each load page but I already had it writing to a database table. I considered changing it but worried that it might take too much memory (probably not a valid concern, but anyway...) So yes, to memory would be an alternate and probably a preferred way to do it. Wanna make the update for me? WA is all about positive participation! :-) Aug 18, 2010 at 15:24
5
votes

Debug Bar Action Hooks plugin

Displays a list of actions fired for the current request. Requires the debug bar plugin.

1
2
votes

The Codex has an Action Reference and a Filter Reference. Adam Brown created a hook database that has all hooks in the source code, and adds the documentation from the wiki pages, version information and links to the source code. You can improve it by writing documentation in the Codex.

Of course, some hooks are dynamic, depending on other data. Take the wp_transition_post_status function:

function wp_transition_post_status($new_status, $old_status, $post) {
    do_action('transition_post_status', $new_status, $old_status, $post);
    do_action("${old_status}_to_$new_status", $post);
    do_action("${new_status}_$post->post_type", $post->ID, $post);
}

If you register a custom post type event and a custom post status cancelled, you will have a cancelled_event action hook.

2
  • Adam Browns database is not just a combination of those 2 pages, it has every single action and filter in WordPress listed. Or is that not what you meant. Aug 13, 2010 at 18:25
  • @Arlen: Yes indeed, I rewrote it so that is more clear.
    – Jan Fabry
    Aug 13, 2010 at 18:56
1
vote

Although primitive, perhaps this plugin code can help? Switch "add_action" with "add_filter" if you want to look at filters instead. Load the plugin and then refresh the homepage of the site. Once loaded, it's a serious pain to deactivate, so just rename the plugin file under the plugins folder and refresh the site again -- it will deactivate automatically. I've used this trick many a time to troubleshoot things or find a place where I can insert something.

<?php
/*
Plugin Name: Hooks
Plugin URI: http://example.com/
Description: Hooks
Version: 1.00
Author: Hooks
Author URI: http://example.com/
*/

add_action('all','hook_catchall');
function hook_catchall(&$s1 = '', &$s2 = '', &$s3 = '', &$s4 = '') {
    echo "<h1>1</h1>\n";
    print_r($s1);
    echo "<br />\n";
    echo "<h1>2</h1>\n";
    print_r($s2);
    echo "<br />\n";
    echo "<h1>3</h1>\n";    
    print_r($s3);
    echo "<br />\n";
    echo "<h1>4</h1>\n";    
    print_r($s4);
    echo "<br />\n";
    return $s1;
}
1
  • It may not be pretty, but it might actually be the quickest and easiest way in some scenarios (I often use “printf debugging” to fix little things in small, Notepad+command-line projects instead of using a whole IDE).
    – Synetech
    Jul 28, 2013 at 17:02
0
votes

I use thiss to find the order of hooks. To get the the filters just change add_action to add_filter.

function echo_all_hooks() {
$not_arr = array('gettext','sanitize_key','gettext_with_context','attribute_escape');
if(!in_array(current_filter(),$not_arr)) echo current_filter()."<br/>";
}
add_action('all','echo_all_hooks');
0
votes

As @kaiser suggest do not post only links i am improving it. but it is not possible to use entire code here so i am using few image here to explain that how it have a complete list for WordPress hooks with describe each. you can find it here for hooks, classes, functions, plugins, enter image description here

to describe each enter image description here

0
votes

You can just use a query monitor plugin: https://wordpress.org/plugins/query-monitor/

enter image description here

Not the answer you're looking for? Browse other questions tagged or ask your own question.