Is it possible to do a custom query and convert it to a standard
WP_Query object?
Yes. You can do something like…
$post_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE ....");
$posts_qry = new WP_Query(array('post__in'=> $posts_ids,'orderby' => 'post__in'));
The second query will preserve the order of results from the first.
I am fairly sure that you cannot make that first query with WP_Query
, or any other function. The logic is too complicated. You’d need a JOIN
or a WHERE
clause that WP_Query
does not support. Unfortunately, writing that SQL
is going to be complicated too, just to get the category.
Completely hand-writing the query is of course your first option. The best I can do without hand-writing any SQL
would be:
$post_ids = new WP_Query(array(
'fields' => 'ids',
'ignore_sticky_posts' => true,
'posts_per_page' => 3,
'cat' => "75", // Only posts within category 75 (News)
));
$post_ids_2 = new WP_Query(array(
'fields' => 'ids',
'ignore_sticky_posts' => true,
'posts_per_page' => 3,
'post__not_in' => $post_ids->posts,
'meta_query' => array(
array(
'key' => '_edit_lock',
'value' => '0',
'compare' => '=',
),
)
));
$post_ids = $post_ids->posts + $post_ids_2->posts;
$posts_qry = new WP_Query(array('post__in'=> $posts_ids,'orderby' => 'post__in'));
That is 3 queries (ouch) and ordering could be an issue if you are worried about that.
Your other option is alter the query via a couple of filters. The WP_Query
arguments are going to deal with the in-the-news = 1
part.
$post_ids_v3 = new WP_Query(array(
'ignore_sticky_posts' => true,
'posts_per_page' => 20,
'my_variable' => true,
// Including posts tagged to show "In the News"
'meta_query' => array(
array(
'key' => 'in-the-news',
'value' => '1',
'compare' => '=',
)
)
));
Notice that you are leaving out your category component and passing an extra unofficial parameter named my_variable
. I do not know if passing additional variables like that is by design, so be aware that that may be unofficial behavior. You are going to use that to add your category component into the query with two filters.
function posts_join_wpse_98652($join,$qry) {
global $wpdb;
if (true === $qry->get('my_variable')) {
$join .= " JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)";
}
return $join;
}
add_filter('posts_join','posts_join_wpse_98652',1,2);
function posts_where_wpse_98652($where,$qry) {
global $wpdb;
if (true === $qry->get('my_variable')) {
$where .= " OR {$wpdb->term_relationships}.term_taxonomy_id IN (75)";
}
return $where;
}
add_filter('posts_where','posts_where_wpse_98652',1,2);
That is not even close to well tested, but it appears to be working when I try. Still, these things can be hard to get right, maybe I’ve made a mistake. Barely tested. Possibly buggy. Caveat emptor. No refunds.