I am trying to write a shortcode, which includes 'get_posts' in order to get the blog posts data and then display the 3 most recent on the page.

This code works within the template. However, when I put it into a shortcode, within output buffering (ob_start), it fails to retrieve the posts. Instead, it takes the current page itself and loops through that instead (in this case the homepage).

Any idea how I can get it to loop through the posts as originally intended?

Here is the code that works in the template:

<?php $lastposts = get_posts( array('posts_per_page' => 3) );?>
<?php if ( $lastposts ) {
    foreach ( $lastposts as $post ) :
        setup_postdata( $post ); ?>
        <div class="single_post" onclick="location.href = '<?php the_permalink(); ?>';">
            <div class="postbox" style="background-image: url('<?php echo catch_first_image() ?>');">
                <div class="pink_cover">
                    <div class="text-center datebox">
                        <h5><?php the_time('j'); ?></h5>
                        <hr>
                        <h6><?php the_time('M'); ?></h6>
                        <h6><?php the_date('Y'); ?></h6>
                    </div>
                </div>
            </div>
            <div class="row infobox">
                <div class="col-9">
                    <h3><a href="<?php the_permalink(); ?>"><?php the_category($separator = ', '); ?></a></h3>
                    <h4><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h4>
                </div>
                <div class="col-3 infobox-moreinfo">
                    <img src="more_info.png">
                </div>
            </div>
        </div>
    <?php endforeach; wp_reset_postdata(); } ?>

Here is the shortcode that, while displays something similar on the page, does not retrieve the blog posts themselves.

add_shortcode('home_blog', function(){
    ob_start();
    ?>
        <?php $lastposts = get_posts( array('posts_per_page' => 3) );?>
            <?php if ( $lastposts ) {
                foreach ( $lastposts as $post ) :
                    setup_postdata( $post ); ?>
                    <div class="single_post" onclick="location.href = '<?php the_permalink(); ?>';">
                        <div class="postbox" style="background-image: url('<?php echo catch_first_image() ?>');">
                            <div class="pink_cover">
                                <div class="text-center datebox">
                                    <h5><?php the_time('j'); ?></h5>
                                    <hr>
                                    <h6><?php the_time('M'); ?></h6>
                                    <h6><?php the_date('Y'); ?></h6>
                                </div>
                            </div>
                        </div>
                        <div class="row infobox">
                            <div class="col-9">
                                <h3><a href="<?php the_permalink(); ?>"><?php the_category($separator = ', '); ?></a></h3>
                                <h4><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h4>
                            </div>
                            <div class="col-3 infobox-moreinfo">
                                <img src="more_info.png">
                            </div>
                        </div>
                    </div>
                <?php endforeach; wp_reset_postdata(); } ?>
        <?php
        $output = ob_get_clean();
        return $output;
});
  • 1
    You might be missing global $post before the foreach loop in your shortcode function. Please refer to the setup_postdata codex entry, codex.wordpress.org/Function_Reference/setup_postdata – Antti Koskinen Oct 25 at 10:57
  • @AnttiKoskinen, you're a genius :) That was it! Thanks, man! If you want to write that as an answer, then I'll mark it as correct. :) – AlmostPitt Oct 25 at 10:59
up vote 2 down vote accepted

You might be missing global $post before the foreach loop in your shortcode function. Please refer to the setup_postdata codex entry.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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