Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am trying to create a modular plugin that includes action hooks for developers to add content before and after the main shortcode content. I'm having some trouble because anything I do in the function called by the action hook is always echoed out at the top of the shortcode instead of inside the shortcode where it belongs.

I've been searching and I did come across this response from Pippin Williams on a recent ThemeForest thread, where he recommends using output buffering. I haven't gotten this to work properly for me, and I've read elsewhere that output buffering should only be used as a last resort, so I'm still looking for a clean solution.

The simplest shortcode ever:

add_shortcode('shortcode','example_shortcode');

function example_shortcode( $atts ) {

  $shortcode_output = "<p>Some shortcode content.</p>";
  $shortcode_output .= "<p>More shortcode content.</p>";

  return $shortcode_output;

}

Now lets add an action:

add_shortcode('shortcode','example_shortcode');

function example_shortcode( $atts ) {

  $shortcode_output = "<p>Some shortcode content.</p>";
  $shortcode_output .= "<p>More shortcode content.</p>";

  do_action('below_shortcode');

  return $shortcode_output;
}

add_action('below_shortcode', 'example_action_output');

function example_action_output() {
    echo "<p>This should be output at the end.</p>";
}

The contents of example_action_output() are returned above the shortcode content because of the echo statement. I tried output buffering as recommended by Pippin:

add_shortcode('shortcode','example_shortcode');

function example_shortcode( $atts ) {

  $shortcode_output = "<p>Some shortcode content.</p>";
  $shortcode_output .= "<p>More shortcode content.</p>";

  ob_start();
  do_action('below_shortcode');
  return ob_get_clean();

  return $shortcode_output;
}

add_action('below_shortcode', 'example_action_output');

function example_action_output() {
    echo "<p>This should be output at the end.</p>";
}

This returned the contents of example_action_output(), but wiped out the rest of my shortcode. Any suggestions?

Thanks, Dalton

share|improve this question
1  
Is anything else hooked to below_shortcode? Could you not implement it as a filter & return the output instead? –  TheDeadMedic Jul 25 '12 at 12:57
    
I was planning to use the hooks to build the plugin internally, and then make those hooks available to developers as well, so yes, theoretically more than one function could be attached to the same hook. –  Dalton Jul 25 '12 at 13:03
    
Just FYI, your version using my output buffer method is incorrect. You have two return statements, meaning only the first one will actually return anything. You should use $shortcode_output .= ob_get_clean(); instead of `return ob_get_clean();'. –  Pippin Jul 25 '12 at 14:01
    
@Pippin: thanks, yeah, figured that out after seeing Kalengi's answer. It all makes sense now. –  Dalton Jul 25 '12 at 14:44
add comment

1 Answer

up vote 1 down vote accepted

Try this:

function example_shortcode( $atts ) {

    $shortcode_output = "<p>Some shortcode content.</p>";
    $shortcode_output .= "<p>More shortcode content.</p>";

    ob_start();
        do_action('below_shortcode');
        $below_shortcode = ob_get_contents();
    ob_end_clean();

    $shortcode_output .= $below_shortcode

    return $shortcode_output;
}
share|improve this answer
    
As the OP mentioned, he wants to avoid output buffering. –  kaiser Jul 25 '12 at 13:15
    
I'd be willing to use output buffering if that's the best way to do it. I guess I need to do more research into output buffering and consider the implications. –  Dalton Jul 25 '12 at 13:19
1  
The good news is that definitely works, so thank you. Now I have a bunch of follow up questions about output buffering and whether I should be using a filter instead of an action to accomplish this. :-) –  Dalton Jul 25 '12 at 13:29
    
The suggestion by @TheDeadMedic is actually a better way to go. The WP way is to use filters if you want users of your plugin to add content to the plugin's output pipeline. –  KalenGi Jul 25 '12 at 15:05
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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