2

I want to reuse code made in a template in a shortcode.

I did this in my shortcode

$args = array(...);             
$posts      = get_posts($args);
for ( $j=0; $j < count($posts); $j++ ) {

    ...
    $post_id = $posts[$j]->ID;

    setup_postdata($posts[$j]);
    ob_start();

    get_template_part( 'includes/post-formats/postbox' );
    $output .= ob_get_contents();
    ob_end_clean();
}

return $output;

Code in the template is something like this:

<div class="post-header span3">
        <?php if(is_sticky()) : ?>
            <h5 class="post-label"><?php echo theme_locals("featured");?></h5>
        <?php endif; ?>
        <h2 class="post-title"><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2>
        <?php
            the_post_thumbnail( 'medium' );
        ?>
    </div>
 <div class="foo">
 <?php the_content(); ?>
 </div>

Well, the problem is that the title and the thumbnail don't work, the title and the thumbnail are shown wrong. Only the content is shown well (via the_content()).

5
  • 3
    You have to use the $post global. setup_postdata( $post ) Commented Jun 29, 2015 at 17:44
  • 1
    If I'm not mistaken, it's probably a good idea to run wp_reset_postdata(); after your loop since you're using setup_postdata() function.
    – Howdy_McGee
    Commented Jun 29, 2015 at 17:58
  • @Howdy_McGee you are correct. setup_postdata changes the global $post value to the current value of the custom loop. You must reset your $post global back to main query ;-) Commented Jun 29, 2015 at 18:14
  • My pleasure, enjoy ;-) Commented Jun 30, 2015 at 6:46
  • 1
    Related: stackoverflow.com/questions/39101020/… Commented May 6, 2018 at 4:04

1 Answer 1

0

For those who aren't creating a query with get_posts() you may need to reference the global $post variable first before using setup_postdata().

Here is an example shortcode using a foreach loop and iterating through an array of post objects from an ACF Relationship field:

function your_shortcode() {
    //reference global $post first
    global $post;

    $featured_posts = get_field('relationship_field'); 
    $html = '';

    ob_start();

    foreach( $featured_posts as $post ): 

        // Setup this post for WP functions (variable must be named $post).
        setup_postdata($post);

        get_template_part('php/components/card', 'project');

    endforeach;

    $html .= ob_get_clean();

    // Reset the global post object so that the rest of the page works correctly.
    wp_reset_postdata(); 

    return $html;

}
add_shortcode( 'your-shortcode', 'your_shortcode' );

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.