I've updated some of the content in this post for more clarity thanks to Stephen's comment

When it comes to retrieving content outside of The Loop or retrieving content based on certain criteria, it’s usually a matter of setting up a custom query using WP_Query.

But sometimes, setting up a full custom query, executing the loop, then resetting the post data isn’t required.

Case in point: I was recently working on a project in which the client wanted a modal dialog to appear with the title and the text from a specific page. Easy enough: use get_page_by_title.

But there’s one minor gotcha that I’ve seen more than a few times when using this method. Here’s how to get post content by title and avoid the pitfalls of doing so.

Get Post Content By Title

Getting the post itself is easy. For purposes of example, I’ll assume that I have a post called “Hello World.”

To get the post, first make a call to get_page_by_title:

// The function is case insensitive, so we can use lower case
$my_post = get_page_by_title( 'hello world', OBJECT, 'post' );

This will return a post object to which we have access to all of the attributes for the post. So, to render the title, we can do something like this:

<h1><?php echo get_the_title( $my_post->ID ); ?></h1>

And to get the content, we can do this:

echo $my_post->post_content;

Except this isn’t the best way to go about rendering the content – you can lose some of the formatting, and, generally speaking, fail to display the post as the author intended it.

Avoid The Pitfall

If you’re rendering the post content using the post_content attribute, then pass it through the_content filter first:

echo apply_filters( 'the_content', $my_post->post_content );

An important thing to note is that if you’re writing this code for use by a number of users or for a large-scale deployment, this function does not respect post status so it can result in an insecurity. Konstantin discusses this more in his comment; however, if you’re writing this for a use case in which a single administrator or team of editors are aware of the functionality, the security risk is a bit lower.

Regardless, this is the best way to make sure that you’re displaying the post as it was written whenever you’re opting to step outside of The Loop or a custom query.

Category:
Notes
Tags:

Join the conversation! 7 Comments

  1. I’ve not tested it, but to output the content (as an alternative to applying the filter).

    setup_postdata( $post );
    the_content();
    wp_reset_postdata( $post );

    should work too, and gives you all the internal shenanigans of the_content().

    Another point is that a lot of plug-ins use global $post inside callbacks on the_content to identify the post – so in either case you might want to declare $post as global.

  2. Interesting read – I’ve never heard of “get_page_by_title”, but you learn something new everyday. My question is what are the limitations of using this as opposed to WP_Query()? I’m supposin’ that you can’t return all the data associated with a post (like custom fields) with this method.

    • It’s not as flexible as WP_Query because it only pulls back the single post object, but you can just as easily retrieve it’s meta data by using the $post->ID attribute.

      As far as pulling back an ordered collection by, say, a certain author or set of authors, you’re better off using WP_Query. After all, this method is used for specifically getting a single post ;).

      Glad to have helped out – thanks for the comment, too!

  3. Note that get_page_by_title will look for pages by default, not posts. You can use its third argument to specify a different post type.

    However, the real pitfall is that your page might be private, or draft, or password protected, and get_page_by_title will totally ignore that, and reveal whatever was intended to be hidden. So if your client has set that page to private or perhaps password protected, your popup modal is still displaying its content to everyone. I call that insecure.

    In this scenario it’s safer to use get_posts or WP_Query, because they both (are essentially the same thing, and) respect the post status. Or at least check $post->post_status after retrieving it.

    Good luck!

    ~ K

    • You’re right about the parameters for the function – updated the post to reflect that, so thanks for bringing that up.

      And though you’re right about the issue with post status – and it is certainly worth mentioning – it also depends on the use case.

      By that, I mean that if you’re writing a plugin or something that’s going to be in use by multiple users, this wouldn’t be the way to go; however, in a scenario where either the client is well aware of the issue or has requested functionality like this, it’s not a much of a problem. I’d say the pitfall is relative.

      Regardless, in the former situation, you’re correct in making sure to distinguish the status post. I’ve also updated to most in mentioning that, too.

      At any rate, always appreciate your comments – definitely adds value to the content and the readership :).

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.