wordpresswordpress-shortcode

How to prevent shortcodes from being executed multiple times


It seems shortcodes added to the front page in Wordpress will execute multiple times, possibly this is expected behavior. For example, adding a shortcode called [myshortcode] to the front page, and defining it like this in functions.php:

function myshortcode()
{ 
     ob_start();

     // This is what really needs to be run only once
     update_my_database();

     return ob_get_clean();
}
add_shortcode('myshortcode','myshortcode');

WordPress seems to execute this multiple times. Can that be prevented? Or is there another way to execute a function one time and only one time on the WP front page without using a shortcode?

I've tried multiple checks including in_the_loop() and is_singular() but none seem to work. Also tried adding remove_shortcode('myshortcode'); within the myshortcode function, thinking that might prevent subsequent executions, but that doesn't work either: Tried adding static variables per https://stackoverflow.com/a/3695685/8552218 but doesn't work.

Here's what it looks like with all these approaches, and this still doesn't work. Any ideas?

function myshortcode()
{ 
     ob_start();

     if (!is_singular()) return ob_get_clean;
     if (!in_the_loop()) return ob_get_clean;
     if (!is_main_query()) return ob_get_clean;

     static $runonce=false;
     if (!$runonce)
     { 
          $runonce=true;
          return;
     }

     // This is what really needs to be run only once
     update_my_database();
     
     remove_shortcode('myshortcode');

     return ob_get_clean();
}
add_shortcode('myshortcode','myshortcode');


function update_my_database()
{
     error_log("Executing...",1,$myemail);
} 

Solution

  • Ok I've been having the same problem. For some reason "the_content" is being fired prior to the page being loaded and I can't find where this hook is being fired and by what plugin. I've written a little hook to only fire my shortcodes on the second time. Though it's not a perfect solution it worked for me in most circumstances.

    Put this in your functions.php file:

    static $sc_already_run = [];
    
    function sc_check_already_run($sc_unique_id){
      global $sc_already_run;
        if(empty($sc_already_run) || !in_array($sc_unique_id,$sc_already_run)){
            //NOT ALREADY RUN, Return false to stop the function
            $sc_already_run[] = $sc_unique_id;
            return false;
        } else {
            //ALREADY RUN, Return true to fire the function
            unset($sc_already_run[$sc_unique_id]);
            return true;
        }
    }
    

    At the beginning of your shortcode insert the following adding in a unique reference, your shortcode's name will do:

     if(!sc_check_already_run("MYSHORTCODENAME")){
        return false;
    }
    

    This simply sets a global static variable we can grab and simply every time the shortcode is run, we're checking if it's already been run.

    You could set this up to only run on the first time with a little config.

    Hope this helps.