Make WordPress Core

Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#20647 closed defect (bug) (invalid)

get_post_type() returns nothing on custom post type archive pages with custom query and no results

Reported by: MikevHoenselaar Owned by: MikevHoenselaar
Milestone: Priority: normal
Severity: normal Version: 3.3.2
Component: Posts, Post Types Keywords: needs-patch
Focuses: Cc:


As following:
I open a custom post type archive page. In my case domain.nl/partners.
Everything works fine here.
We have a custom filter and use ?bg={number}?country={number} to filter on custom field on that archive page.

We use the pre_get_posts action for that. We set the meta_query query var via ->set().

When we do this and use a {number} in the $_GET that doesn't exists. Obviously we have 0 results.
So $post remains empty in the get_posts() function.

In a lot of plugins and in this case WordPress SEO of Yoast is a function get_post_type() being used. The function relies on $post to function properly.

When there are no results, no $post, no post_type. But I believe we can work with the queried_vars here.
get_query_var( 'post_type' ); to fix it. My solution:

function get_post_type( $the_post = false ) {

global $post;
if ( false === $the_post )

$the_post = $post;

elseif ( is_numeric($the_post) )

$the_post = get_post($the_post);

if ( is_object($the_post) )

return $the_post->post_type;


return get_query_var ('post_type');

return false;


Change History (8)

comment:1 scribu2 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Status changed from new to closed

If you're using query_posts() and it whipes out the $post global, the solution isn't to patch get_post_type(), but to call wp_reset_query() or wp_reset_postdata().

comment:2 scribu2 years ago

wp_reset_postdata() does exactly what you want: restores the $post global from the main query. Works for new WP_Query() too.

comment:3 scribu2 years ago

Oh, and if you absolutely need a function that uses the query vars, there's get_queried_object(), which will return the post type object, if called from a post type archive.

Let's keep get_post_type() tied to the $post global, for the sake of everyone's sanity.

comment:4 MikevHoenselaar2 years ago

I expected that get_post_type() would give me the post_type of the query I did. It's post only. If the main_query on the archive page isn't returning anything get_post_type() isn't useful now. But it can be useful to get a post_type.
So you are saying that Yoast will have to edit his plugin and use a !empty($post_type) after using get_post_type()?

I know that you can have your own if, then, elses in your plugin. And probably Yoast shouldn't take for granted that there always is a $post_type returned from get_post_type().
But I believe get_post_type can be better :-).

Adding this will make sure that I always will get a post_type if there is one.

comment:5 scribu2 years ago

Here's what the docs say:

 * Retrieve the post type of the current post or of a given post.
 * @since 2.1.0
 * @uses $post The Loop current post global
 * @param mixed $the_post Optional. Post object or post ID.
 * @return bool|string post type or false on failure.
function get_post_type( $the_post = false ) {

You should think of it as belonging to the same family as get_post_status() and get_the_title().

comment:6 scribu2 years ago

Also note that get_query_var( 'post_type' ) can return an array. That's probably something most plugins aren't prepared for either.

So, my suggestion is that they should decide what they want: the post type of a certain post or the post type from the query vars? In the unlikely case when they would want both, they can just call both functions.

comment:7 scribu2 years ago

I would actually be for deprecating get_post_type(), since the name is misleading and it's not that useful as a template tag either. Plus you can just call get_post()->post_type now.

comment:8 DrewAPicture2 years ago

  • Cc xoodrew@… added
Note: See TracTickets for help on using tickets.