I have a plugin that is returning post IDs based on $_GET data (which searches a secondary DB table). I am attempting to hook into the standard have_posts() function called within a taxonomy page to show the results. Since the data is passed in on the actual page, I can't use the normal pre_get_posts stand-by, like so:
function finder_sort($query) {
if ($query->is_main_query() && is_tax(array('location_type')) && isset($_GET['finder_action'])) {
$query->set('post__in', array(1,2,3,4,5));
}
}
add_action('pre_get_posts','finder_sort');
Because the data returned is not available until after the $_GET requests have been read on the page. So - I was wondering if there's anything I can filter in right before the data is output. For example, here is what I have:
$locations_found = wp_list_pluck($locations, 'id');
while(have_posts()) {
the_post();
echo '<tr>';
finder_location_teaser_table();
echo '</tr>';
}
$locations_found has a list of IDs - so what I'm looking to do is filter have_posts to only include the IDs listed in $locations_found.
In addition, I need these posts ordered as they are noted in post__in. Since WP 3.5 is going to "fix" this, I've already added in the Sort Query by Post In function fix:
if ( version_compare( floatval( get_bloginfo( 'version' ) ), '3.5', '<' ) ) {
add_filter( 'posts_orderby', 'sort_query_by_post_in', 10, 2 );
function sort_query_by_post_in( $sortby, $thequery ) {
if ( !empty($thequery->query['post__in']) && isset($thequery->query['orderby']) && $thequery->query['orderby'] == 'post__in' )
$sortby = "find_in_set(ID, '" . implode( ',', $thequery->query['post__in'] ) . "')";
return $sortby;
}
}
so - it'd be a mixture of identifying the post__in and then specifying the order_by param in this magical filter. Any thoughts would be greatly appreciated. Thanks!
Clarification
The reason I cannot use the meta key (and why I need to return them in the same order they are retrieved by) is because there is a calculation done on each data item that is dependent on another $_GET variable (distance based on zip code).
Addition Info
Added display function that generates query vars
function finder_top_filter($term) {
ob_start(); ?>
<section id="sort">
<form name="search" action="" method="get">
<label for="finder_zipcode"><?php _e('Zip Code', 'finder'); ?></label>
<input type="text" name="finder_zipcode" id="finder_zipcode" value="<?php echo isset($_GET['finder_zipcode']) ? $_GET['finder_zipcode'] : ''; ?>" />
<label for="finder_distance"><?php _e('Radius', 'finder'); ?></label>
<select name="finder_distance" id="finder_distance">
<?php
$finder_dist_options = apply_filters('finder_dist_options', array(
'5' => '5',
'10' => '10',
'25' => '25',
'50' => '50',
'100' => '100',
'200' => '200'
));
foreach ($finder_dist_options as $key=>$value) {
echo '<option value="' . $key . '" ' . (isset($_GET['finder_distance']) ? selected( $_GET['finder_distance'], $key ) : '') . '>' . $value . '</option>';
}
?>
</select>
<input type="hidden" name="finder_action" value="search" />
<input type="submit" value="<?php _e('Show/Filter', 'finder'); ?>" />
<span class="reset"><a href="<?php echo get_term_link($term); ?>">Reset</a></span>
</form>
</section>
<?php
echo ob_get_clean();
}
Update
Based on the recommendation of Stephen Harris, I decided to go the route of a JOIN query to alter the data passed to the loop. So, what I've tried is:
function finder_join_locations($join) {
global $wpdb;
return '';
}
add_filter('posts_join', 'finder_join_locations');
$i = 0;
while(have_posts()) {
the_post();
echo '<tr>';
finder_location_teaser_table(get_the_ID(), $locations[$i]['distance']);
echo '</tr>';
$i++;
}
remove_filter('posts_join', 'finder_join_locations');
To see if I can get nothing to show, but that filter is not overriding the have_posts() function - any recommendations? What I'd like to do is pass-in via the post__in param, so after I get past this initial bump, it's figuring out the correct SQL statement to include my data (as $locations_found includes all the post data I need):
$locations_found = wp_list_pluck($locations, 'id');
$locations- which is only available in the template? How do you set$locations? All query manipulation (for the 'main' query) should ideally be done outside the template... – Stephen Harris Dec 2 '12 at 15:03post__in" - this second part is unrelated to the solution to the first part. Please post it as a separate question. – Chip Bennett Dec 2 '12 at 15:15JOINquery to sort by distance on the main query rather than running two separate queries. – Stephen Harris Dec 4 '12 at 14:52