/************************************************************************\ |** **| |** Allow WP_Query() search function to look for multiple keywords **| |** in metas in addition to post_title and post_content **| |** **| |** By rAthus @ Arkanite **| |** Created: 2020-08-18 **| |** Updated: 2020-08-19 **| |** **| |** Just use the usual 's' argument and add a 's_meta_keys' argument **| |** containing an array of the meta(s) key you want to search in :) **| |** **| |** Example : **| |** **| |** $args = array( **| |** 'numberposts' => -1, **| |** 'post_type' => 'post', **| |** 's' => $MY_SEARCH_STRING, **| |** 's_meta_keys' => array('META_KEY_1','META_KEY_2'); **| |** 'orderby' => 'date', **| |** 'order' => 'DESC', **| |** ); **| |** $posts = new WP_Query($args); **| |** **| \************************************************************************/ add_action('pre_get_posts', 'akn_meta_search_query'); // add the special search fonction on each get_posts query (this includes WP_Query()) function akn_meta_search_query($query) { if ($query->is_search() and $query->query_vars and $query->query_vars['s'] and $query->query_vars['s_meta_keys']) { // if we are searching using the 's' argument and added a 's_meta_keys' argument global $wpdb; $search = $query->query_vars['s']; // get the search string $ids = array(); // initiate array of matching post ids per searched keyword foreach (explode(' ',$search) as $term) { // explode keywords and look for matching results for each $term = trim($term); // remove unnecessary spaces if (!empty($term)) { // check the the keyword is not empty $query_posts = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_status='publish' AND ((post_title LIKE '%%%s%%') OR (post_content LIKE '%%%s%%'))", $term, $term); // search in title and content like the normal function does $ids_posts = []; $results = $wpdb->get_results($query_posts); if ($wpdb->last_error) die($wpdb->last_error); foreach ($results as $result) $ids_posts[] = $result->ID; // gather matching post ids $query_meta = []; foreach($query->query_vars['s_meta_keys'] as $meta_key) // now construct a search query the search in each desired meta key $query_meta[] = $wpdb->prepare("meta_key='%s' AND meta_value LIKE '%%%s%%'", $meta_key, $term); $query_metas = $wpdb->prepare("SELECT * FROM {$wpdb->postmeta} WHERE ((".implode(') OR (',$query_meta)."))"); $ids_metas = []; $results = $wpdb->get_results($query_metas); if ($wpdb->last_error) die($wpdb->last_error); foreach ($results as $result) $ids_metas[] = $result->post_id; // gather matching post ids $merged = array_merge($ids_posts,$ids_metas); // merge the title, content and meta ids resulting from both queries $unique = array_unique($merged); // remove duplicates if (!$unique) $unique = array(0); // if no result, add a "0" id otherwise all posts will be returned $ids[] = $unique; // add array of matching ids into the main array } } if (count($ids)>1) $intersected = call_user_func_array('array_intersect',$ids); // if several keywords keep only ids that are found in all keywords' matching arrays else $intersected = $ids[0]; // otherwise keep the only matching ids array $unique = array_unique($intersected); // remove duplicates if (!$unique) $unique = array(0); // if no result, add a "0" id otherwise all posts will be returned unset($query->query_vars['s']); // unset normal search query $query->set('post__in',$unique); // add a filter by post id instead } }