0

How can I add a single WordPress function for all WordPress actions/event.

I want to add something equivalent to the one which is below

add_Action('All WordPress Event/Actions', 'My_Function');

And also I wanted to make this function compatible such a way that I will get all system implicit arguments like below

  • My_Function($content);

  • My_Function($postId);

$content and $postId are implicit arguments passed by WordPress system...

2 Answers 2

4

There is a special action all that you can use. Be aware, this will be very slow, don’t do that in production.

Here is an example:

add_action( 'all', function() {

    static $hooks = [];

    $filter = current_filter();

    if ( isset ( $hooks[ $filter ] ) )
        return;

    $types  = array_map( function ( $arg ) {
        return gettype( $arg );
    }, func_get_args() );

    $hooks[ $filter ]  = count( $types ) . ' arguments: ' . join( ",\t", $types );

    if ( 'shutdown' !== $filter )
        return;

    $text = "\n\nFILE: " . $_SERVER['REQUEST_URI'] . ' ' . date( 'Y.m.d. H:i:s' ) . "\n\n";

    foreach ( $hooks as $hook => $args )
        $text .= str_pad( $hook, 50 ) . " => $args\n";

    $file = WP_CONTENT_DIR . '/hook.log';
    file_put_contents( $file, $text, FILE_APPEND | LOCK_EX );
});

Now you get all hooks listed in a file hooks.log. Sample output:

FILE: /wp-admin/admin-ajax.php 2015.03.29. 17:25:41

muplugins_loaded                                   => 1 arguments: string
pre_site_option_siteurl                            => 2 arguments: string,  boolean
site_option_siteurl                                => 2 arguments: string,  string
pre_option_siteurl                                 => 2 arguments: string,  boolean
option_siteurl                                     => 2 arguments: string,  string
gettext_with_context                               => 5 arguments: string,  string, string, string, string
gettext                                            => 4 arguments: string,  string, string, string
registered_taxonomy                                => 4 arguments: string,  string, string, array
sanitize_key                                       => 3 arguments: string,  string, string
post_type_labels_post                              => 2 arguments: string,  object
registered_post_type                               => 3 arguments: string,  string, object
post_type_labels_page                              => 2 arguments: string,  object
post_type_labels_attachment                        => 2 arguments: string,  object
post_type_labels_revision                          => 2 arguments: string,  object
post_type_labels_nav_menu_item                     => 2 arguments: string,  object
theme_root                                         => 2 arguments: string,  string
pre_option_active_plugins                          => 2 arguments: string,  boolean
…
12
  • Can you please let me know how i can access the content of those arguments and also i need a working solution which i can use in my production env... Mar 29, 2015 at 17:38
  • The content is the $arg. You can use that in production, but it will slow down your site, because there are so many actions. Try to find the one action that you need and use just that, not all actions.
    – fuxia
    Mar 29, 2015 at 17:40
  • my requirement is to do for actions, please let know a better solution... Mar 29, 2015 at 17:44
  • 2
    There is no better solution that I am aware of. Fix the requirement.
    – fuxia
    Mar 29, 2015 at 17:56
  • can you please let me know how i can get the argument name? Mar 29, 2015 at 18:38
1

This is a very very bad idea.

You can achieve this by doing something like this:

add_action( 'init', function(){
    do_action()//rinse recycle repeat for every hook
});

I highly highly HIGHLY recommend you do not take this route. It can cause a lot of problems of hooks firing when not needed etc.

The idea of a hook is to extend the functionality of the process being processed at the given time, they are supplied data that is only available during certain actions like adding comments.

If you do_action for every single hook, it could be catastrophic. Not to mention you'd not have data for each hook.

If you are looking to fire a function literally every time a page is loaded, then use the init hook, for admin panel only use admin_init

But don't fire every single WordPress action in one hook. It's just not a good idea

Just to cover all grounds

Do:

add_action( 'init', function(){
    add_action( 'hook', function(){
        // do code here
    })
})

This will fire the function on every hook but don't fire every hook on one hook. Of course you would do a separate add_action for every hook you wanted to fire the function on, but there is no real way to fire hooks.

A little better route to reuse code could be:

add_action( 'init', function(){
    $hooks = array(
            'hook1',
            'hook2',
            'hook3'//and so on.
        );

    foreach( $hooks as $hook ){

        add_action( $hook, function(){
            // Do code
        });
    }

    // Do the same but in add_filter
});

Again to cover all grounds, this method directly above would add the action / filter but the action / filter would not fire until it is fired with apply_filter or do_action, this simply just adds the function to the action or filter.

Then you'd have to work on accepting the args of the function, without supplying the 4th argument on add_action you are guaranteed only 1 argument so you would have to filter in your code what argument you are work with, with some if or elses.

In response to a comment to elaborate on the arg you could do something similar to:

add_action( 'init', function(){
        $hooks = array(
                'hook1' => array( 'argname1', 'argname2', 'argname3' ),
                'hook2' => array( 'argname1', 'argname2', 'argname3' ),
                'hook3' => array( 'argname1', 'argname2', 'argname3' )//and so on.
            );

        foreach( $hooks as $hook=>$args  ){
            add_action( $hook, function(){

                $numargs = func_num_args();
                for( $i=0; $i<$numargs; $i++ ){
                    $$args[$i] = func_get_arg($i);
                }
                // Do code
            }, 10, count( $args ) );
        }

        // Do the same but in add_filter
    });

Then with the for you'd obviously judge the number of args you need to avoid errors.

To better avoid errors, check the $args[$i] exists or is not empty, before setting a func_get_arg to it.

Response to comment: here's a real time example of how you would use this with save_post action

add_action( 'init', function(){
    $hooks = array(
        'save_post' => array( 'post_id', 'post', 'update' )
    );

    foreach( $hooks as $hook=>$arg ){
        add_action( $hook, function(){ // Note we dont do any args here  
            $num_args = func_num_args(); // would return 3 because we supplied 3 args
            for( $i=0; $i<$num_args; $i++ ){
                if( !empty( $arg[$i] ) ){
                    $$arg[$i] = func_get_arg( $i );
                    // We use !empty as it will check if isset AND not empty
                    // This would set all three array values to the respective variable
                    //       $post_id, $post, $update
                    // Make sure you put the args in the right order in the hooks array above to avoid mixing up var names.

                }
            }

            if( isset( $post ) ){
               update_post_meta( $post->ID, 'meta_key_whatever_you_want', 'meta_value_whateveryouwant' );
                // I used $post to show you that the second argumnet supplied by do_action is $post and we set $$arg[1] as $post and retrieved the arg with same key 1 Normally you would just use post_id

            }

            // Can do with any of the args just be carefull.
        }, 10, count( $args ) ); 
        // We count the hook arg array which is the array with simple strings for our variable names and supply it to add_action to let wordpress know we want 3 arguments. If you supply more than 3 arguments you may get errors for this hook, so setting array with 50 args for a hook that only supplies 3 is not good.
        // 10 is simply priority in which this hook fires.
    }
});

This is just one way you can do this, then you would just do a array key for hook and array for arguments for each hook and check if the variable is set. You may want to do some additional verification on variables to make sure you have the right data as some hooks share variable names, though you can customize, so $post_id can be set to $$arg[0] and in the arg array set as 'post_id_custom' which would be set to $post_id_custom with the hooks $post_id supplied data.

One more thing, to really completely simplify things you can do this too:

function someFunc(){
 // do code here
}

add_action('hook1', 'someFunc' );
add_action('hook2', 'someFunc' );
add_action('hook3', 'someFunc' );
add_action('hook4', 'someFunc' );

this will fire the same fun with all of the action hooks supplied.

add_action( 'all', function() {
    static $hooks = [];
    global $allhooks;

    $filter = current_filter();

    if ( isset ( $hooks[ $filter ] ) )
        return;

    $types  = array_map( function ( $arg ) {
        return $arg;
    }, func_get_args() );

    $hooks[$filter] = $types;

    if( 'shutdown' !== $filter )
        return;

    foreach( $hooks as $hook=>$args ){
        $allhooks[$hook] = $args;
    }

});

add_action( 'shutdown', function(){
    global $allhooks;
    var_dump( $allhooks );
});

This will print all hooks and all args that come with the hooks fyi. Simple modification of toscho's code, it var_dumps something like this for every hook.

array (size=809)
  'after_setup_theme' => 
    array (size=1)
      0 => string 'after_setup_theme' (length=17)
  'ot_theme_mode' => 
    array (size=2)
      0 => string 'ot_theme_mode' (length=13)
      1 => boolean false
  'ot_child_theme_mode' => 
    array (size=2)
      0 => string 'ot_child_theme_mode' (length=19)
      1 => boolean false
  'ot_show_pages' => 
    array (size=2)
      0 => string 'ot_show_pages' (length=13)
      1 => boolean true

This just dumps it to the browser, simply reiterating and helping explain to you what toscho is saying that argument names are not supplied only values.

After review, it's missing hooks like save_post. So even the all hook doesn't supply every action and filter.

There really is no way to accomplish this, and it is really a bad idea.

Again I'm not a WordPress expert.

14
  • Hello David, thanks a lot for the help. can you please let me know how will i be able to access the system implicit arguments, like for any instance of function call, i should be able to access the hook name and if it is a post related event i should be able to access $content, $postId etc inside that function... Mar 29, 2015 at 17:12
  • Sure ill edit now Mar 29, 2015 at 17:13
  • You could do something like that, but that may not be best practice. Mar 29, 2015 at 17:19
  • To elaborate a little further, see the latest edit and in the argname1, argname2 array you would put the name or the variable name you wish to use for that arg. By double casting $ liek $$arg[$i] you are setting that array string as the variable name. so $arg[0] is argname1 would be set to $argname1 and be usable in that fashion. Mar 29, 2015 at 17:23
  • David,could you please post a small Real Time snippet of code for post event... Mar 29, 2015 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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