How many times will this code run? (or, how rich is grandma?)

Here are some random thoughts on this:

Question #1

How much money did we send to grandma?

For 100 page loads, we sent her 100 x $1 = $100.

Here we actually mean 100 x do_action( 'init' ) calls.

It didn’t matter that we added it twice with:

add_action( 'init','send_money_to_grandma' );
add_action( 'init','send_money_to_grandma' );

because the callbacks and priorities (default 10) are identical.

We can check how the add_action is just a wrapper for add_filter that constructs the global $wp_filter array:

function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
        global $wp_filter, $merged_filters;

        $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
        $wp_filter[$tag][$priority][$idx] = array(
            'function'      => $function_to_add, 
            'accepted_args' => $accepted_args
        );
        unset( $merged_filters[ $tag ] );
        return true;
}

If we did however change the priority:

add_action( 'init','send_money_to_grandma', 9 );
add_action( 'init','send_money_to_grandma', 10 );

then we would send her 2 x $1 per page load or $200 for 100 page loads.

Same if the callbacks where different:

add_action( 'init','send_money_to_grandma_1_dollar' );
add_action( 'init','send_money_to_grandma_also_1_dollar' );

Question #2

If we want to make sure we only send grandma $1

If we only want to send it once per page load, then this should do it:

add_action( 'init','send_money_to_grandma' );

because the init hook is only fired once. We might have other hooks that fires up many times per page load.

Let’s call:

add_action( 'someaction ','send_money_to_grandma' );

but what happens if someaction fires 10 times per page load?

We could adjust the send_money_to_grandma() function with

function send_money_to_grandma() 
{
    if( ! did_action( 'someaction' ) )
        internetofThings("send grandma","$1");
}

or use a static variable as a counter:

function send_money_to_grandma() 
{
    static $counter = 0;
    if( 0 === $counter++ )
        internetofThings("send grandma","$1");
}

If we only want to run it once (ever!), then we might register an option in the wp_options table via the Options API:

function send_money_to_grandma() 
{
    if( 'no' === get_option( 'sent_grandma_money', 'no' ) )
    {
        update_option( 'sent_grandma_money', 'yes' );
        internetofThings( "send grandma","$1" );
    }
}

If we want to send her money once every day, then we can use the Transient API

function send_money_to_grandma() 
{
    if ( false === get_transient( 'sent_grandma_money' ) ) )
    {
        internetofThings( "send grandma","$1" );
        set_transient( 'sent_grandma_money', 'yes', DAY_IN_SECONDS );
    }
}

or even use the wp-cron.

Note that you might have ajax calls. as well.

There are ways to check for those, e.g. with DOING_AJAX

There might also be redirections, that could interrupt the flow.

Then we might want to restrict to the backend only, is_admin() or not: ! is_admin().

Question #3

Is this something that plugin developers worry about?

yes this is important.

If we want to make our grandma very happy we would do:

add_action( 'all','send_money_to_grandma' );

but this would be very bad for performance … and our wallet 😉

Leave a Comment