Skip to content

Instantly share code, notes, and snippets.

@tammyhart
Last active August 29, 2015 14:20
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tammyhart/138971bb9d1f97c30090 to your computer and use it in GitHub Desktop.
Save tammyhart/138971bb9d1f97c30090 to your computer and use it in GitHub Desktop.
Traverse WordPress Search Results
<?php
/**
* Return search array
*/
function loopconf_search_array( $search_hash ) {
// check for existence of unique transient
if ( false === ( $search_array = get_transient( 'loopconf_search_' . $search_hash ) ) ) {
global $wpdb;
$posts = $wpdb->get_results( $GLOBALS['wp_query']->request );
$search_array = array();
if ( false === empty( $posts ) ) {
foreach ( $posts as $post ) {
$search_array[] = $post->ID;
}
}
// save the transient for 10 minutes
set_transient( 'loopconf_search_' . $search_hash, $search_array, MINUTE_IN_SECONDS * 10 );
}
return $search_array;
}
/**
* Set session search_string
*/
function loopconf_set_search_string() {
global $wp_query;
$wp_session = WP_Session::get_instance();
// if we’re on a search page, save the search data
if ( !is_admin() && is_search() && isset( $wp_query->query_vars_hash ) ) {
$search_string = $wp_query->query['s'];
$search_hash = $wp_query->query_vars_hash;
$wp_session['search_string'] = $search_string;
$wp_session['search_hash'] = $search_hash;
$wp_session['search_array'] = loopconf_search_array( $search_hash );
}
// if we’re anywhere else, clear the search data
if ( !is_admin() && !is_search() && !is_single() && is_main_query() ) {
$wp_session['search_string'] =
$wp_session['search_hash'] =
$wp_session['search_array'] = null;
}
}
add_action( 'pre_get_posts', 'loopconf_set_search_string' );
/**
* Get the next or previous post in the array
*/
function loopconf_get_next_search_result( $next = true ) {
$wp_session = WP_Session::get_instance();
// make sure there’s a search saved in the session
if ( isset( $wp_session['search_array'] ) === false ) {
return false;
}
// set variables
$next_key = 0;
$search_array = $wp_session['search_array']->toArray();
$current_key = array_search( get_the_ID(), $search_array );
// get next or previous location in the array
if ( $next === true ) {
$next_key = $current_key + 1;
if ( isset( $search_array[$next_key] ) === false ) {
$next_key = 0;
}
} else {
$next_key = $current_key - 1;
if ( isset( $search_array[$next_key] ) === false ) {
end( $search_array );
$next_key = key( $search_array );
}
}
// return value from that location
return $search_array[$next_key];
}
?>
<?php
$prev_url = $next_url = false;
// get next and prev search results or just the links
if ( loopconf_get_next_search_result() ) {
$wp_session = WP_Session::get_instance();
$prev_url = get_permalink( loopconf_get_next_search_result() ); false ) );
$next_url = get_permalink( loopconf_get_next_search_result() );
} else {
$prev_url = get_previous_post();
$next_url = get_next_post();
}
?>
<div class="single-nav">
<a href="<?php echo esc_url( $prev_url ); ?>" class="prev">Previous</a>
<a href="<?php echo esc_url( $next_url ); ?>" class="next">Next</a>
</div>
@richardbuff
Copy link

I'm confused on one point here. Function loopconf_search_array is accessing $GLOBALS['wp_query']->request . But loopconf_search_array is called from pre_get_posts. At this point in the WP lifecycle, since the SQL for the query has not been generated yet, and since $GLOBALS['wp_query']->request holds the SQL for the query, how is the line below ever not empty?
$posts = $wpdb->get_results( $GLOBALS['wp_query']->request );

@tammyhart
Copy link
Author

Good question. Probably just me doing my usual checks.

@richardbuff
Copy link

But the code relies on $posts getting populated by $wpdb->get_results returning something. And $wpdb->get_results is using $GLOBALS['wp_query']->request, which, when I tried to use it, will not be set yet, because at pre_get_posts time, the SQL has not been generated yet.

@tammyhart
Copy link
Author

TBH, it's been so long since I originally wrote this, I'm not sure where I got that method from. All I can say is that it does return the correct posts. you can unwrap it from the transient settings and print it out to see for yourself.

@richardbuff
Copy link

So I've figured out what was confusing me. loopconf_search_array gets called for EVERY query on the search page. And since the SQL isn't created yet on the first call, if there's only one query on the page, it will fail. The second time pre_get_posts fires, which happens when there's at least 2 queries, everything will be set as expected. I was testing it with a version of 2015 that didn't have the menu configured, or any widgets in the sidebar, so it was failing for me. As soon as I added anything to the page that created another query, it worked fine and dandy. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment