get_posts() loop returns the same the_title() for each post

I'm using get_posts() to fetch posts from a particular category to display at the top of my homepage, separate from the main homepage Loop. Everything seems to work fine, but for the title (returned through the_title()) which is always the same; the title of the first post fetched by get_posts(). the_permalink() does the same as well, but the_excerpt() returns the correct result for each post.

Here's my code (I have removed only a few lines for fear I might inadvertently remove what is causing this problem):

$query = get_posts(array(
    'numberposts'=-1,
    'category'=3
    ));
$events = array();

if ($query) {
    foreach ($query as $tpost) {
        $fields = get_post_custom($tpost-ID);
        if (isset($fields['event_start'])) {
            $usetime = $fields['event_start'][0];
            if (isset($fields['event_end'])) {
                $usetime = $fields['event_end'][0];
                }
            if ($usetimetime()) {
                $events[] = array("post"=$tpost,"fields"=$fields);
                }
            }
        }
    usort($events,function($a,$b){
        $a = $a['fields']['event_start'][0];
        $b = $b['fields']['event_start'][0];
        if ($a==$b) { return 0; }
        return ($a  $b) ? -1 : 1;
        });
    }

if (count($events)0) { ?
    div class="pad10 tac"
    h2 class="mar10"Upcoming Events/h2
    div class="tiles"
    ?php foreach ($events as $event ) { ?
        ?php setup_postdata( $event['post'] );?
        a href="?php the_permalink(); ?" class='noshow'
        div class="tile smalltile"div id='post-?php the_ID(); ?'
            h2?php the_title();?/h2
            b?php
            echo(date_i18n("D, F j @ g:ia",$event['fields']['event_start'][0]));
            ?/b
            p?php the_excerpt();?/p
        /div/div
        /a
    ?php }?
    /div/div
?php }?

I'm really scratching my head on this, especially as this code is, for the most part, based off of the get_posts() example from this article, where it is reportedly working fine.

I'm thinking that this likely has something to do with my use of setup_postdata, but I suppose this is really just wild speculation.

Topic get-the-title get-posts query Wordpress

Category Web


Use setup_postdata() for that.

Important setup_postdata() does not assign the global $post variable so it’s important that you do this yourself.

Important use wp_reset_postdata() after your foreach loop.

For more information visit: https://developer.wordpress.org/reference/functions/setup_postdata/

<?php
    // Get posts
    global $post;
    $posts = get_posts([
        'post_type' => 'post',
        'numberposts' => 6
    ]);
?>

<?php foreach ($posts as $key => $post): ?>
    <?php setup_postdata($post); ?>
    <h3>
        <a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
            <?php the_title(); ?>
        </a>
    </h3>
<?php endforeach; ?>
<?php wp_reset_postdata(); ?>

Making Milos's comment into an answer....

The problem you are facing is the result of many wordpress template oriented functions expect some global variables. In WP_Query based loops setting those variable is done by calling the the_post() method of the WP_Query object, but with get_posts you need to call setup_postdata() for that.

My personal preference is to just try to avoid functions like the_title in favor of functions like get_the_title, that accept an explicit post id, whenever possible.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.