Posted on

Restrict search by author from the search query

You can set Relevanssi to index the post author, which will then let you find posts by searching for the name of the author. But what if you want a stricter filter? Where searching for an author would only show posts by that one author, and nothing else? That’s possible too.

Add this function to your theme functions.php to implement a stricter author filtering. Whenever a search is made, Relevanssi will fetch a list of authors on your site and then will compare the list of authors against the search query. If a match is made, Relevanssi will then add the author ID to the author parameter and remove the author name from the search query. The search will only match one author, the first one it comes across.

add_filter( 'relevanssi_modify_wp_query', 'rlv_author_filter' );
function rlv_author_filter( $query ) {
	$author_list = get_transient( 'rlv_author_filter_author_list' );
	if ( ! $author_list ) {
		$args        = array(
			'show_fullname' => false,
			'hide_empty'    => true,
			'echo'          => false,
			'style'         => '',
			'html'          => false,
			'exclude_admin' => false,
		);

		$author_list = wp_list_authors( $args );
		set_transient( 'rlv_author_filter_author_list', $author_list, WEEK_IN_SECONDS );
	}
	$authors = explode( ', ', $author_list );

	foreach ( $authors as $author ) {
		if ( false !== mb_stristr( $query->query_vars['s'], $author ) ) {
			$args= array(
				'search'        => $author,
				'search_fields' => array( 'display_name' )
			);
			$user_query = new WP_User_Query( $args );
			$results    = $user_query->get_results();
			if ( ! empty( $results) ) {
				$query->query_vars['s'] = str_ireplace( $author, '', $query->query_vars['s'] );
				$query->query_vars['author'] = $results[0]->ID;
				break;
			}
		}
	}

	return $query;
}

There’s a small lesson in the power of caching here as well. Notice the $author_list is taken from a transient, and only if it doesn’t exist, it’s generated with wp_list_authors(). The transient is stored for a week – because in most cases the list of authors is fairly stable – so the function needs to be called just once per week.

Why is this? I noticed in my tests that adding that one function call – just a single function – actually generated 200 database queries. A search without the user filter generated ~50 queries, a search with the filter did ~250 queries. Your mileage may vary, depending on the number of authors on your site for example, but it’s clear that is potentially a very expensive function. Since it produces output that’s stable and easy to cache, it’s a very good example of how you can optimize and cache using the transients.

If you have a very stable list of authors, it’s not a bad idea to remove the whole affair with wp_list_authors() and the transients, and instead just list all the authors you want to include directly as the $authors array.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.