Tag Archives: get_posts

The problems of get_posts() and custom post_type’s

Allright, Generally i’d not complain, I’d just make up a new Trac ticket and patch it.. But i’m seriously sick of this defect of WP_Query, A number of times i’ve just given up attempting to achieve my goal and doing it some other method which wouldnt involve hacking up everything..

The problem?

Add a new record to the WP_Posts table, with a custom post_type, now try to retrieve that post. Ah, I hear you say “Thats Easy! Just pass post_type to get_posts()” WRONG!,
Well, yes, In an ideal world, that would be the case, But no, not in this case.

First, Lets add an actual record:

[sourcecode language="php"]
$url = ‘http://dd32.id.au/';
$content = ‘DD32 is awesome!';
$datas = array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘custom_status’, ‘post_title’ => $url, ‘post_name’ => $url, ‘guid’ => md5($url), ‘post_content’ => $content);
wp_insert_post($datas);
[/sourcecode]

What have i done? Just inserted a stock standard post of type ‘custom_type’ with a non-standard status. Nothing odd there.

Now, Lets retrieve that post.

First thing, Lets check that get_posts() can handle a custom post_type:

[sourcecode language="php"]
var_dump( get_posts( array(‘post_type’ => ‘custom_type’) ) );

array
empty
[/sourcecode]

Allright, That didnt work, Better check the query used:

[sourcecode language="sql"]SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_type = ‘custom_type’ AND (wp_posts.post_status = ‘publish’) ORDER BY wp_posts.post_date DESC LIMIT 0, 5[/sourcecode]

Ah, It doenst like our post_status, Not a probblem, Letslet it load all status types:

[sourcecode language="php"]
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’) ) );

array
0 =>
object(stdClass)[132]
public ‘ID’ => string ‘571’ (length=3)
public ‘post_author’ => string ‘2’ (length=1)
public ‘post_date’ => string ‘2008-11-12 16:47:06′ (length=19)
public ‘post_date_gmt’ => string ‘2008-11-12 05:47:06′ (length=19)
public ‘post_content’ => string ‘DD32 is awesome!’ (length=16)
public ‘post_title’ => string ‘http://dd32.id.au/’ (length=18)
public ‘post_category’ => string ‘0’ (length=1)
public ‘post_excerpt’ => string ” (length=0)
public ‘post_status’ => string ‘custom_status’ (length=13)
public ‘comment_status’ => string ‘open’ (length=4)
public ‘ping_status’ => string ‘open’ (length=4)
public ‘post_password’ => string ” (length=0)
public ‘post_name’ => string ‘httpdd32idau’ (length=12)
public ‘to_ping’ => string ” (length=0)
public ‘pinged’ => string ” (length=0)
public ‘post_modified’ => string ‘2008-11-12 16:47:06′ (length=19)
public ‘post_modified_gmt’ => string ‘2008-11-12 05:47:06′ (length=19)
public ‘post_content_filtered’ => string ” (length=0)
public ‘post_parent’ => string ‘0’ (length=1)
public ‘guid’ => string ‘9b159fde538e1d5b84949ae427f50168′ (length=32)
public ‘menu_order’ => string ‘0’ (length=1)
public ‘post_type’ => string ‘custom_type’ (length=11)
public ‘post_mime_type’ => string ” (length=0)
public ‘comment_count’ => string ‘0’ (length=1)
[/sourcecode]

Looks good to me, Everything seems to have been set correctly.

However, hang on, What happens when i only want to retrieve a specific item? Well, I guess we need to specify some arguements to retrieve a single record:

[sourcecode language="php"]
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘p’ => 571 ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘page_id’ => 571 ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘name’ => $url ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘pagename’ => $url ) ) );
[/sourcecode]

One of those should return something.. Right? Well.. Lets look:

[sourcecode language="php"]
array
empty
array
empty
array
empty
array
empty
[/sourcecode]

Nope, Not a thing.. What the?

Lets go check those queries again…

[sourcecode language="sql"]
8 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.ID = 571 AND wp_posts.post_type = ‘post’ ORDER BY wp_posts.post_date DESC ‘ (length=135)
1 => float 0.000998020172119
2 => string ‘get_posts’ (length=9)
9 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.ID = 571 AND wp_posts.post_type = ‘page’ ORDER BY wp_posts.post_date DESC ‘ (length=135)
1 => float 0.00107502937317
2 => string ‘get_posts’ (length=9)
10 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = ‘httpdd32idau’ AND wp_posts.post_type = ‘post’ ORDER BY wp_posts.post_date DESC ‘ (length=153)
1 => float 0.00149297714233
2 => string ‘get_posts’ (length=9)
11 =>
array
0 => string ‘SELECT ID, post_name, post_parent FROM wp_posts WHERE post_name = ‘dd32idau’ AND (post_type = ‘page’ OR post_type = ‘attachment’)’ (length=129)
1 => float 0.00108218193054
2 => string ‘get_page_by_path’ (length=16)
12 =>
array
0 => string ‘SELECT ID, post_name, post_parent FROM wp_posts WHERE post_name = ‘dd32idau’ AND (post_type = ‘page’ OR post_type = ‘attachment’)’ (length=129)
1 => float 0.000935077667236
2 => string ‘get_page_by_path’ (length=16)
13 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND (wp_posts.ID = ‘0’) AND wp_posts.post_type = ‘page’ ORDER BY wp_posts.post_date DESC ‘ (length=137)
1 => float 0.000837087631226
2 => string ‘get_posts’ (length=9)
[/sourcecode]

Well, Let me first say, No idea why the last case has caused 3 queries (which are near unique), But thats not the interesting part.. Notice the post_type? Its no longer set to our requested ‘custom_type‘ oops, Lets go back and check that code, Wait! I did specify it!.

Eugh. Thank you WP_Query, Of course you know better than I do, Sorry i questioned your judgement and requested something else!

Time to hook in and tell WP_Query I know best..

[sourcecode language="php"]
function stupid_post_type_custom_type($query) {
if ( isset($query->query_vars['post_type']) && ‘custom_type’ == $query->query_vars['post_type'] )
$query->is_page = $query->is_single = $query->is_attchment = false;
}
$url = ‘http://dd32.id.au/';

add_action(‘parse_query’, ‘stupid_post_type_custom_type’, 10, 1);
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘p’ => 571 ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘page_id’ => 571 ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘name’ => $url ) ) );
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘pagename’ => $url ) ) );
remove_action(‘parse_query’, ‘stupid_post_type_custom_type’, 10, 1);
[/sourcecode]

WooHoo!

[sourcecode language="php"]
array
0 =>
object(stdClass)[131]
public ‘ID’ => string ‘571’ (length=3)
public ‘post_author’ => string ‘2’ (length=1)
public ‘post_date’ => string ‘2008-11-12 16:47:06′ (length=19)
public ‘post_date_gmt’ => string ‘2008-11-12 05:47:06′ (length=19)
public ‘post_content’ => string ‘DD32 is awesome!’ (length=16)
public ‘post_title’ => string ‘http://dd32.id.au/’ (length=18)
public ‘post_category’ => string ‘0’ (length=1)
public ‘post_excerpt’ => string ” (length=0)
public ‘post_status’ => string ‘custom_status’ (length=13)
public ‘comment_status’ => string ‘open’ (length=4)
public ‘ping_status’ => string ‘open’ (length=4)
public ‘post_password’ => string ” (length=0)
public ‘post_name’ => string ‘httpdd32idau’ (length=12)
public ‘to_ping’ => string ” (length=0)
public ‘pinged’ => string ” (length=0)
public ‘post_modified’ => string ‘2008-11-12 16:47:06′ (length=19)
public ‘post_modified_gmt’ => string ‘2008-11-12 05:47:06′ (length=19)
public ‘post_content_filtered’ => string ” (length=0)
public ‘post_parent’ => string ‘0’ (length=1)
public ‘guid’ => string ‘9b159fde538e1d5b84949ae427f50168′ (length=32)
public ‘menu_order’ => string ‘0’ (length=1)
public ‘post_type’ => string ‘custom_type’ (length=11)
public ‘post_mime_type’ => string ” (length=0)
public ‘comment_count’ => string ‘0’ (length=1)
array
0 =>
object(stdClass)[133]
public ‘ID’ => string ‘571’ (length=3)
public ‘post_author’ => string ‘2’ (length=1)
public ‘post_date’ => string ‘2008-11-12 16:47:06′ (length=19)
public ‘post_date_gmt’ => string ‘2008-11-12 05:47:06′ (length=19)
public ‘post_content’ => string ‘DD32 is awesome!’ (length=16)
public ‘post_title’ => string ‘http://dd32.id.au/’ (length=18)
public ‘post_category’ => string ‘0’ (length=1)
public ‘post_excerpt’ => string ” (length=0)
public ‘post_status’ => string ‘custom_status’ (length=13)
public ‘comment_status’ => string ‘open’ (length=4)
public ‘ping_status’ => string ‘open’ (length=4)
public ‘post_password’ => string ” (length=0)
public ‘post_name’ => string ‘httpdd32idau’ (length=12)
public ‘to_ping’ => string ” (length=0)
public ‘pinged’ => string ” (length=0)
public ‘post_modified’ => string ‘2008-11-12 16:47:06′ (length=19)
public ‘post_modified_gmt’ => string ‘2008-11-12 05:47:06′ (length=19)
public ‘post_content_filtered’ => string ” (length=0)
public ‘post_parent’ => string ‘0’ (length=1)
public ‘guid’ => string ‘9b159fde538e1d5b84949ae427f50168′ (length=32)
public ‘menu_order’ => string ‘0’ (length=1)
public ‘post_type’ => string ‘custom_type’ (length=11)
public ‘post_mime_type’ => string ” (length=0)
public ‘comment_count’ => string ‘0’ (length=1)
array
0 =>
object(stdClass)[133]
public ‘ID’ => string ‘571’ (length=3)
public ‘post_author’ => string ‘2’ (length=1)
public ‘post_date’ => string ‘2008-11-12 16:47:06′ (length=19)
public ‘post_date_gmt’ => string ‘2008-11-12 05:47:06′ (length=19)
public ‘post_content’ => string ‘DD32 is awesome!’ (length=16)
public ‘post_title’ => string ‘http://dd32.id.au/’ (length=18)
public ‘post_category’ => string ‘0’ (length=1)
public ‘post_excerpt’ => string ” (length=0)
public ‘post_status’ => string ‘custom_status’ (length=13)
public ‘comment_status’ => string ‘open’ (length=4)
public ‘ping_status’ => string ‘open’ (length=4)
public ‘post_password’ => string ” (length=0)
public ‘post_name’ => string ‘httpdd32idau’ (length=12)
public ‘to_ping’ => string ” (length=0)
public ‘pinged’ => string ” (length=0)
public ‘post_modified’ => string ‘2008-11-12 16:47:06′ (length=19)
public ‘post_modified_gmt’ => string ‘2008-11-12 05:47:06′ (length=19)
public ‘post_content_filtered’ => string ” (length=0)
public ‘post_parent’ => string ‘0’ (length=1)
public ‘guid’ => string ‘9b159fde538e1d5b84949ae427f50168′ (length=32)
public ‘menu_order’ => string ‘0’ (length=1)
public ‘post_type’ => string ‘custom_type’ (length=11)
public ‘post_mime_type’ => string ” (length=0)
public ‘comment_count’ => string ‘0’ (length=1)
array
empty
[/sourcecode]

Wait!, Why is that last case still returning nothing?

Query time again..

[sourcecode language="sql"]
8 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.ID = 571 AND wp_posts.post_type = ‘custom_type’ ORDER BY wp_posts.post_date DESC ‘ (length=142)
1 => float 0.00179696083069
2 => string ‘get_posts’ (length=9)

11 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.ID = 571 AND wp_posts.post_type = ‘custom_type’ ORDER BY wp_posts.post_date DESC ‘ (length=142)
1 => float 0.000961065292358
2 => string ‘get_posts’ (length=9)
12 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = ‘httpdd32idau’ AND wp_posts.post_type = ‘custom_type’ ORDER BY wp_posts.post_date DESC ‘ (length=160)
1 => float 0.00102686882019
2 => string ‘get_posts’ (length=9)
13 =>
array
0 => string ‘SELECT ID, post_name, post_parent FROM wp_posts WHERE post_name = ‘dd32idau’ AND (post_type = ‘page’ OR post_type = ‘attachment’)’ (length=129)
1 => float 0.00131893157959
2 => string ‘get_page_by_path’ (length=16)
14 =>
array
0 => string ‘SELECT ID, post_name, post_parent FROM wp_posts WHERE post_name = ‘dd32idau’ AND (post_type = ‘page’ OR post_type = ‘attachment’)’ (length=129)
1 => float 0.00103116035461
2 => string ‘get_page_by_path’ (length=16)
15 =>
array
0 => string ‘ SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND (wp_posts.ID = ‘0’) AND wp_posts.post_type = ‘custom_type’ ORDER BY wp_posts.post_date DESC ‘ (length=144)
1 => float 0.00140690803528
2 => string ‘get_posts’ (length=9)
[/sourcecode]

Ok, Seems using ‘pagename’ query parameter just isnt going to work, It’s been hard coded to work off ‘page’ or ‘attachment’ regardless, And when it finally does fall through to using custom_type.. It’s forgotten it was using pagename, and instead, is trying to use an ID..

Moral of the story? the parse_query hook is your friend; But make sure to only modify those queries which you’re using, and not all the core WP_Query queries too..

The working code:

[sourcecode language="php"]
function stupid_post_type_custom_type($query) {
if ( isset($query->query_vars['post_type']) && ‘custom_type’ == $query->query_vars['post_type'] )
$query->is_page = $query->is_single = $query->is_attchment = false;
}
$url = ‘http://dd32.id.au/';

add_action(‘parse_query’, ‘stupid_post_type_custom_type’, 10, 1);
var_dump( get_posts( array(‘post_type’ => ‘custom_type’, ‘post_status’ => ‘any’, ‘name’ => $url ) ) );
remove_action(‘parse_query’, ‘stupid_post_type_custom_type’, 10, 1);
[/sourcecode]

EDIT: ARGH. Ok, WP/the Syntax Highlighter plugin have had a war, They dont like the idea of not touching stuff within the sourcecode shortcode.. I’m pretty sure i had a Trac ticket for that….