(Revised on March 25 2020 UTC)
So in this revised answer, I’ll just begin with the code:
-
Define the variables: (I intentionally included only the
$args
part)// define POSTed/submitted variables here like $paged, $display_count and $direction // define the offset/'direction' stuff here // then define your $args array $args = array( 'post_type' => 'product', 'post_status' => 'publish', 'orderby' => 'menu_order', 'order' => 'ASC', 'posts_per_page' => $display_count, // You should use 'paged' and not 'page'. 'paged' => $paged, 'offset' => $offsetcalc >= 1 ? $offsetcalc : '', 'tax_query' => array(), );
-
And here’s the main code, for the “search term OR”:
// This is basically $args['tax_query'], except that we *don't* add it to $args. $tax_query = array(); if ( ! empty( $search_tags ) ) { $tax_query[] = array( 'taxonomy' => 'product_tag', 'terms' => wp_parse_slug_list( $search_tags ), 'field' => 'slug', ); } if ( ! empty( $search_categories ) ) { $tax_query[] = array( 'taxonomy' => 'product_cat', 'terms' => wp_parse_slug_list( $search_categories ), 'field' => 'slug', ); } if ( ! empty( $tax_query ) ) { // if empty, don't set the relation $tax_query['relation'] = $search_relation; } $_filter = true; // a (private) var for the closure below add_filter( 'posts_clauses', function ( $clauses ) use ( &$_filter, $search_term, $tax_query ) { if ( ! $_filter ) { return $clauses; } global $wpdb; $search_where=""; if ( $search_term ) { $like="%" . $wpdb->esc_like( $search_term ) . '%'; $search_where = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $like ); } if ( ! empty( $tax_query ) ) { $tax_query = new WP_Tax_Query( $tax_query ); $is_and = ( 'AND' === $tax_query->relation ); $tax_query = $tax_query->get_sql( $wpdb->posts, 'ID' ); if ( empty( $tax_query['where'] ) ) { // just in case.. if ( $search_where ) { $clauses['where'] .= " AND ( $search_where )"; } return $clauses; } $clauses['join'] .= $tax_query['join']; if ( $is_and ) { $clauses['where'] .= $search_where ? " AND ( $search_where ) {$tax_query['where']}" : $tax_query['where']; } else { $where = preg_replace( '/^ *AND\b/', '', $tax_query['where'] ); $clauses['where'] .= $search_where ? " AND ( ( $search_where ) OR{$where} )" : $tax_query['where']; } $clauses['groupby'] = "$wpdb->posts.ID"; } elseif ( $search_where ) { $clauses['where'] .= " AND ( $search_where )"; } return $clauses; } ); $the_query = new WP_Query( $args ); $_filter = false; // disable the filter, to avoid issues with other WP_Query calls
A bit of explanation (for code #2 above)
What you’re looking for is a WHERE
clause that looks something like:
(There are other conditions/variations, but this is the main one)
WHERE post_type="product" AND (
( post_title LIKE '%<search term>%' ) # Find posts that matched the search term,
OR ( product_tag IN (<ids/slugs>) ) # ..or those that are in the specified tags
OR ( product_cat IN (<ids/slugs>) ) # ..or categories.
)
So in that code #2 above, I’m using the posts_clauses
hook to add that WHERE
clause (and do other relevant stuff), but for generating the proper SQL clauses for the taxonomy (tag/category) queries, I’m using WP_Tax_Query
(which is what WP_Query
uses, btw).
Additional Notes
-
I’m using
wp_parse_slug_list()
to parse the (comma-separated) tags and categories into an array of slugs. And you should also be using it to make sure we have a valid array and because the function just works well. 🙂 -
Remember that if
offset
is0
, then in the$args
, theoffset
should be set to''
(i.e. an empty string) instead of0
, to make sure the$paged
works as expected. -
Just a personal note… sorry, I forgot about using
WP_Tax_Query
before. 😉