20

I'm using a shortcode to pull in different loops via the loops-name.php. For some reason it is always at the top of the page. I googled it and using echo instead of return causes that problem but with my code I am not using echo. Here's the shortcode:

// setup the shortcode for use
function friendly_loop_shortcode( $atts, $content = null ) {
extract( shortcode_atts( array(
'category' => '',
'module' => ''
), $atts ) );

include(locate_template('loop-'.$module.'.php'));
 }

Any idea why this is happening?

6
  • Shortcode for including a file? I find it a little odd. Commented Apr 10, 2012 at 12:39
  • 1
    'with my code I am not using echo' - are the loop-module.php files echoing or returning their output?
    – Michael
    Commented Apr 10, 2012 at 12:45
  • Not at the moment - the file just has a paragraph tag with "test" written into it so I can see how it works.
    – john joe
    Commented Apr 10, 2012 at 13:54
  • use get_template_part('loop',$module) instead, it's prettier, quicker to type, supports parent/child themes, and it's the recommended method of including templates in wordpress ( yes locate_template may do some of those things but look how much less readable it is!)
    – Tom J Nowell
    Commented Apr 11, 2012 at 10:00
  • possible duplicate of The result of a shortcode appear BEFORE page content Commented Apr 11, 2012 at 12:06

2 Answers 2

23

You can buffer the output like this:

ob_start();
include(locate_template('loop-'.$module.'.php'));
return ob_get_clean();

EDIT. I tried this, worked fine.

function friendly_loop_shortcode( $atts, $content = null ) {
     extract( shortcode_atts( array(
         'category' => '',
         'module' => ''
     ), $atts ) );

     ob_start();
     include(locate_template('loop-'.$module.'.php'));
     $output = ob_get_clean();
     //print $output; // debug
     return $output;
}

if (!is_admin()) {
     add_shortcode('test', 'friendly_loop_shortcode' );
}
3
  • 4
    Do not use output buffering if there are other ways.
    – fuxia
    Commented Apr 10, 2012 at 19:42
  • 1
    I'm afraid that didn't work.
    – john joe
    Commented Apr 11, 2012 at 6:38
  • what went wrong? I tried and updated the answer
    – offroff
    Commented Apr 11, 2012 at 7:54
12

Your included file is essentially echo-ing HTML. For instance

<?php
 //Some PHP
 echo 'test';
 //Some more PHP
 ?>

Is the same as

<?php
 //Some PHP 
 ?>
 test
<?php
 //Some more PHP
 ?>

Both get printed immediately rather than returned. Since its printed it appears before the page content. You need to return something for it be included in the content.

As @RutwickGangurde pointed out - it's unusual to include a template file in a shortcode.

6
  • 1
    Thanks, I didn't know that. So I need to put the whole thing into a variable and return it? As for including a template file - well I want to make it as easy as possible for the theme users to customise the theme and having a huge shortcode file nested away from the root theme dir is not really ideal for them.
    – john joe
    Commented Apr 10, 2012 at 14:06
  • See @offroff's answer - that should work Commented Apr 10, 2012 at 14:50
  • 1
    "well I want to make it as easy as possible for the theme users to customise the theme" - Just how many abstraction layers are necessary? You've got a custom template file inside of a shortcode. I don't see how that makes things any easier for users. If you want to provide the ability to add static content to all posts, just define a dynamic_sidebar() inside the Loop, and let users add Widgets. Commented Apr 11, 2012 at 12:12
  • Most of the theme users will not appreciate having to trawl through a massive shortcode file to change a simple css class on the frontend. If I break up everything using the standard loop-name.php system then it's a lot faster for them to find what they need. Not ideal but I've got to keep them happy ;)
    – john joe
    Commented Apr 11, 2012 at 13:10
  • Very well explained; Commented Jan 20, 2018 at 17:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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