As you may know the WordPress functions the_content() and get_the_content(), unlike their get_the_title() counterpart, cannot be used outside the loop. Naively ‘in the loop’ means just making sure the $post variable is global and points to the desired post.
So when someone asked why their code wasn’t working when they had used get_the_title() without passing it a post ID or declaring $post as global, the answer was simple.
What they said next threw me.
I find it extremely strange that the_content() works and that my $post variable is indeed an object full of data just like it should.
That is odd. But it turns out that get_the_content() doesn’t really use the $post global. Inspecting the source we see that it actually uses the $pages global. This stores the post’s content (pages as a post can carry across multiple pages). This is actually set up in: setup_postdata().
So while get_the_title() and co use the $post global, the_content() and get_the_content() rely on setup_postdata(). The upshot is that if using these outside the actual ‘Loop’ be sure to do both:
$posts = get_posts(array(...));
if( $posts ){
foreach( $posts as $post ){
global $post;
setup_postdata();
//Use the template tags
}
}
wp_reset_postdata();
Note, while setup_postdata() doesn’t set up the $post global, wp_reset_postdata() does reset it.
Then, while reading this post by Tom McFarlin I thought it might sometimes be useful to be able to retrieve post content by passing the post ID, the same way you can with get_the title()…
Get The Content by ID
/**
* Display the post content. Optinally allows post ID to be passed
* @uses the_content()
*
* @param int $id Optional. Post ID.
* @param string $more_link_text Optional. Content for when there is more text.
* @param bool $stripteaser Optional. Strip teaser content before the more text. Default is false.
*/
function sh_the_content_by_id( $post_id=0, $more_link_text = null, $stripteaser = false ){
global $post;
$post = &get_post($post_id);
setup_postdata( $post, $more_link_text, $stripteaser );
the_content();
wp_reset_postdata( $post );
}
Example usage:
sh_the_content_by_id(2283);
Tweet
Just use get_post_field( ‘post_content’, $post_id )
Hi Kristian,
Thanks, I had forgotten about that one! However, that will just return the entire content
$post->post_content. Unfortunately (as far as I’m aware) it doesn’t pass it throughthe_contentfilter or split the content into pages.My understanding was that
get_post_field()was more intended for admin-side: editing/saving posts – but its still a handy function nonetheless.Thanks for commenting!