The comments left in my code explain what's going on.
protected function fetchLocationByTitle($title) {
/*
* The WP Query class returns wrong post when searching by title using the
* structure below
*
* $query = new \WP_Query([
* 'post_type' => 'location-data',
* 'posts_per_page' => 1,
* 'page' => 1, // Tried removing this per Tom Nowell's post, but still get wrong post.
* 'post_status' => 'publish',
* 'post_title' => $title
* ]);
*
* So to work around we'll pull it ourselves
*/
global $wpdb;
// Changed to $wpdb->prepare per Tom Nowell's comment.
$id = $wpdb->get_results($wpdb->prepare(
"SELECT `ID`
FROM `wp_posts`
WHERE `post_title` = %s
AND `post_type` = 'location-data'
AND `post_status` = 'publish'
LIMIT 1", $title));
if ($id && count($id)) {
$id = $id[0]->ID;
/*
* With ID in hand we can pull a post object normally now.
*/
return $this->parseLocation(\get_post($id));
} else {
return null;
}
}
Can anyone spot why it fetches a different post from the correct one I can get with my direct query?
The comments left in my code explain what's going on.
protected function fetchLocationByTitle($title) {
/*
* The WP Query class returns wrong post when searching by title using the
* structure below
*
* $query = new \WP_Query([
* 'post_type' => 'location-data',
* 'posts_per_page' => 1,
* 'page' => 1, // Tried removing this per Tom Nowell's post, but still get wrong post.
* 'post_status' => 'publish',
* 'post_title' => $title
* ]);
*
* So to work around we'll pull it ourselves
*/
global $wpdb;
// Changed to $wpdb->prepare per Tom Nowell's comment.
$id = $wpdb->get_results($wpdb->prepare(
"SELECT `ID`
FROM `wp_posts`
WHERE `post_title` = %s
AND `post_type` = 'location-data'
AND `post_status` = 'publish'
LIMIT 1", $title));
if ($id && count($id)) {
$id = $id[0]->ID;
/*
* With ID in hand we can pull a post object normally now.
*/
return $this->parseLocation(\get_post($id));
} else {
return null;
}
}
Can anyone spot why it fetches a different post from the correct one I can get with my direct query?
We should be able to fix the query by doing this instead:
$query = new \WP_Query([
'post_type' => 'location-data',
'posts_per_page' => 1,
'post_status' => 'publish',
'title' => $title
]);
This is because page
is unnecessary and may not be the parameter you actually needed, paged
would have been more appropriate, but it too is unnecessary.
Most importantly though, post_title
is not a parameter of WP_Query
according to the docs, instead it lists title
. post_title
is only mentioned as a parameter for search columns.
you can simply use get_posts()
:
$posts = get_posts( [
'title' => $title,
'post_status' => 'publish',
'post_type' => 'location-data',
'posts_per_page' => 1,
] );
https://developer.wordpress/reference/functions/get_posts/
esc_sql
should never be used that way and doesn't work as an arbitrary SQL escaping function despite what its name suggests, you should instead be usingwpdb->prepare
to insert variables into SQL statements. Also when you say search, can you clarify if you're providing an exact match, or expecting it to find similar things? I also see your SQL statement does not specifypage
,page
may be incorrect as the docs say: "Show the number of posts that would show up on page X of a static front page.", are you sure you didn't meanpaged
? I don't think it's necessary to specify – Tom J Nowell ♦ Commented May 22 at 13:33posts_per_page
to check if the result you want is found but not the first result? Have you checked forpre_get_post
filters modifying the query variables? – Tom J Nowell ♦ Commented May 22 at 21:03