I am not sure why but I have used get_posts() to query for some data. Then I used setup_postdata() ... I think its used so that I can use functions like the_permalink() etc with the new post data?

<?php foreach ($childPosts as $cp) : setup_postdata($cp); ?>

<article <?php post_class() ?> id="post-<?php the_ID(); ?>">
  <h1><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h1>
  <?php if (has_post_thumbnail()) : ?>
  <a href="<?php the_permalink() ?>"><?php the_post_thumbnail(($hasOutputNotFeaturedDiv) ? 'thumb-small' : null) ?></a>
  <?php endif; ?>
  <?php the_excerpt(); ?>
  <p class="more"><a href="<?php the_permalink() ?>">Read more ...</a></p>
  <?php include (TEMPLATEPATH . '/inc/meta.php' ); ?>

<?php endforeach; ?>

but it appears that only the_excerpt contains the new post data value, why is that? I find that if I use echo get_the_permalink($cp) it works ok. But I think the shorter version will be better

6 Answers 6


I could be wrong, but from what I'm seeing, "setup_postdata()" should be used when doing a custom select query (not just query_posts): http://codex.wordpress.org/Displaying_Posts_Using_a_Custom_Select_Query

As well, if you want to use tags like "the_title()" and "the_permalink()" with that custom select query ... you'll need to use the variable name $post specifically (not another variable name) in setup_postdata() - AS WELL - you should call global $post before your "foreach" loop...

So basically follow that example in that codex link. And don't change the variable name $post - otherwise it breaks it.


  • 6
    "you should call global $post" . YES! Why is that not in the Codex
    – AlxVallejo
    Apr 26, 2014 at 17:11
  • 2
    2021 and this still causes me issues lol Feb 25, 2021 at 12:04

Replace the

foreach ( $childPosts as $cp ) : setup_postdata( $cp );


foreach ( $childPosts as $post ) : setup_postdata( $post );

So you need to use the exact $post variable along with the setup_postdata().

  • This fixed the the problem I was having. Cheers mate
    – Jeff K.
    Mar 2, 2012 at 22:05
  • 6
    Somebody buy this man a beer! Thank you.. Any idea why/how a local variable can mess with setup_postdata() ?
    – Odys
    Nov 7, 2016 at 14:09
  • 3
    Weird. It seems so illogical to require a specific variable name when you're passing it as a parameter.
    – Gavin
    Dec 14, 2018 at 7:51
  • 4
    @Gavin I don't know why more people don't question how weird some of the WP logic is. The strangeness is just normal now it seems ...
    – JDandChips
    Jul 24, 2020 at 16:47
  • 1
    Another beautiful implementation by Automattticcc.
    – marek.m
    Nov 4, 2021 at 15:22

global post; does not work with setup_postdata($post); if you want to use the the_title() family of commands etc.

It's in https://codex.wordpress.org/Function_Reference/setup_postdata

Instead use

// global $post; setup_postdata($post_object); //don't do this!
setup_postdata( $GLOBALS['post'] =& $post_object );

...also make sure your $post_object is a valid WP_Post object.

  • 1
    This answer actually solves the problem, instead of scolding the OP :p
    – nodws
    Nov 23, 2017 at 23:20

Depending on where you are using setup_postdata() (if it is not in the main loop, or in a function/sidebar widget, for example), you may also need to declare -

global $post;

2 important things to make this work,

  1. use global $post variable to setup the postdata, else the loop functions will not see your custom post object.

  2. VERY IMPORTANT: make sure to call wp_reset_postdata() function at the end of the loop else you may have weird errors which will be very difficult to debug.

     global $post;
     $myposts = get_posts( array(
         'posts_per_page' => 5,
         'offset'         => 1,
         'category'       => 1
     ) );
     if ( $myposts ) :
         foreach ( $myposts as $post ) :
           setup_postdata( $post ); ?>
             <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>

When querying posts just use the normal loop with a set of arguments passed into it. Then reset the query at the end.


    // makes query respect paging rules
    $paged = get_query_var('paged');

    // defining the arguements for the custom loop
    $variablenameQuery = array(
        'post_type'                 => 'seating-charts',
        'post_status'               => 'publish',
        'cust_tax_name'             => 'custom-tax-term',
        'posts_per_page'            => -1, // neg 1 means all posts
        'orderby'                   => 'date',
        'order'                     => 'ASC',
        'paged'                     => $paged,
    ); // end query

    // pass result into query_posts to get result

<?php if (have_posts()) : ?>

    <?php while (have_posts()) : the_post(); ?>

        <?php // Individual Post Styling ?>

    <?php endwhile; ?>

        <?php // paged navigation - next post, previous post... ?>

    <?php else : ?>

    <h3>Ooops looks like there was an issue. Please <a href="<?php echo get_option('home'); ?>/contact" title="Contact Us">get in touch</a> with us and we'll get the problem fixed.</h3>

<?php endif; ?>

<!-- resets the WordPress Query -->
<?php wp_reset_query(); ?>
  • Thanks, this works. But just for understanding, do you know why setup_postdata() does not seem to work? Did I use it wrongly?
    – Jiew Meng
    Feb 19, 2011 at 15:16
  • 1
    @jiewmeng - See if using $post instead of $cp fixes the problem.
    – t31os
    Feb 20, 2011 at 1:28
  • I vote for the fix @t31os suggests. The examples on the codex show the usage like that and $post is a special variable in WordPress so it might do more inside a loop than what you've used. Feb 20, 2011 at 1:54
  • @t31os, @curtismchale, that didn't appear to work too. It still gives the same result
    – Jiew Meng
    Feb 20, 2011 at 2:11
  • Old, I know but DO NOT use query_posts() unless you KNOW you need it. It's inefficient. See this helpful image for the alternatives: rarst.net/images/query_functions.png
    – Tex0gen
    Mar 29, 2023 at 14:00

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.