rAthus icon

[WordPress] WP_Query() search multiple keywords in post title description and metas (ACF, etc)

rAthus | PRO | 03/21/23 11:11:06 AM UTC (Edited) | 0 ⭐ | 2739 👁️ | Never ⏰ | []
PHP |

4.55 KB

|

None

|

0 👍

/

0 👎

/************************************************************************\
|**                                                                    **|
|**  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
    }
}

Comments