setup_postdata
takes a post object of type \WP_Post
, but you’re passing it a WP_Query
instead
e.g.
global $post;
setup_postdata( $post );
Thankfully the solution is trivial, when you call the_post
, it sets up the current post data for you, so removing that line is all you need to do.
The second issue is that WP_Query
will filter out private posts if you’re not logged in, so setting the post status to private is necessary.
An important thing you’re missing though is the clean up call. You need to call wp_reset_postdata()
when you’re done so that code that runs after your loop has the current post and not the last post in your query.
Here’s what that query might look like:
$the_query = new WP_Query( array(
'id' => '1457'
'post_type' => 'page',
'post_status' => 'private'
) );
if ( $the_query->have_posts() ) {
while( $the_query->have_posts() ) {
$the_query->the_post();
// do something;
}
wp_reset_postdata();
}
There’s a faster way though, you already know the post ID, so we can do this:
$p = get_post( 1457 );
if ( null !== $p ) {
setup_postdata( $p );
// do things
wp_reset_postdata();
}