Calling WordPress get_template_part from inside a shortcode function renders template first

Gary O. Stenstrom picture Gary O. Stenstrom · Sep 7, 2012 · Viewed 10.5k times · Source

I have a page where I need to allow the user to enter a paragraph of text. Then after that text, insert a shortcode that will render a list of posts, then add more free-form text after that. My thought was that they should be able to insert a shortcode which will output the posts. This way they can simply add the shortcode where they wish the posts to appear.

I currently have the logic which retrieve the posts separated in its own file. Currently I include it in a page by simply using the get_template_part() function:

get_template_part('donation', 'posts');

I looked into how to create a shortcode and included the following code into my functions.php file in order to create the shortcode:

add_shortcode('donation-posts', 'fnDonatePosts');   
function fnDonatePosts($attr, $content)
{
    get_template_part('donation', 'posts');    
}

The donation-posts.php is being properly executed and the posts are appearing, however, they are always positioned BEFORE the content and not in the location that the shortcode was placed.

I have tried removing the get_template_part() function and just output some text and that works fine. So I understand that the get_template_part() may not be the right way to do this, however, I have not been able to uncover a way to do what I am attempting to do (I am sure that there is a way... I just haven't found it).

I have tried:

include(get_template_directory(). '/donation-posts.php');
include_once(get_template_directory(). '/donation-posts.php') : 

But these stopped processing once they hit the PHP code in the included file.

I have also tried:

$file = file_get_contents(get_template_directory(). '/donation-posts.php');  
        return $file;

But this only returns the contents of the file (as the function name indicates) which means it doesn't execute the PHP script to return the posts.

Anybody out there done this before?

Answer

The Alpha picture The Alpha · Sep 7, 2012

You may try this, it may solve your problem because get_template_part basically reacts like PHP's require, it doesn't return but echos the content immediately where it's been called.

add_shortcode('donation-posts', 'fnDonatePosts');   
function fnDonatePosts($attr, $content)
{        
    ob_start();  
    get_template_part('donation', 'posts');  
    $ret = ob_get_contents();  
    ob_end_clean();  
    return $ret;    
}