Filter search query to exclude postmeta value

In my wordpress site I am making use of the pre_get_posts filter to customise my site search query. In functions file I have the following below.

Now my issue is, using FieldManager I have added a custom meta field called hide_from_search_results which is now included in my wp_postmeta table, with either a 0 or 1 value. Not all posts/pages will have this field set however. I need to add the condition to not show anything that has this set to 1.

First I have joined the wp_posts and wp_postmeta tables like so:

function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search()  !is_admin() ) {
        $join .=' LEFT JOIN '.$wpdb-postmeta. ' ON '. $wpdb-posts . '.ID = ' . $wpdb-postmeta . '.post_id ';
    }

    return $join;
}
add_filter('posts_join', 'cf_search_join' );

I then group the results by the post ID:

function cf_posts_groupby($groupby) {
    global $wpdb;

    if (is_search()  !is_admin()) {
        return $wpdb-posts . '.' . 'ID';
    }

    return $groupby;
}
add_filter( 'posts_groupby', 'cf_posts_groupby' );

Modify the search query with posts_where for things like excluding images from the results:

function cf_search_where( $where ) {
    global $pagenow, $wpdb;

    if ( is_search()  !is_admin() ) {
        $where = preg_replace(
            /\(\s*.$wpdb-posts..post_title\s+LIKE\s*(\'[^\']+\')\s*\)/,
            (.$wpdb-posts..post_title LIKE $1) OR (.$wpdb-postmeta..meta_value LIKE $1), $where );
        
        $where .= ' AND ' . $wpdb-posts . '.post_mime_type != image/jpeg';
    }

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

I lastly then use pre_get_posts to alter the query to include certain post types and only showing published:

function cf_posts_query( $query ) {
    if ( is_search()  !is_admin() ) {

        if (isset($_GET['post_types'])) {
            $query-set('post_type', $_GET['post_types']);
        } else {
            $query-set('post_type', ['page']);
        }

        $query-set( 'post_status', array( 'publish', 'inherit' ) );
      
    }

   return $query;
}
add_filter( 'pre_get_posts', 'cf_posts_query' );

I have tried adding the following into my pre_get_posts

    $query-set( 'meta_query', array(
        array(
          'key' = 'hide_from_search_results',
          'compare' = '!=',
          'value' = '1'
        )
      ));

But get the following error:

WordPress database error: [Not unique table/alias: 'wp_postmeta']
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id WHERE 1=1 AND wp_posts.ID NOT IN (4440,4436) AND (((wp_posts.post_title LIKE '%coron%') OR (wp_postmeta.meta_value LIKE '%coron%') OR (wp_posts.post_excerpt LIKE '%coron%') OR (wp_posts.post_content LIKE '%coron%'))) AND ( ( wp_postmeta.meta_key = 'hide_from_search_results' AND wp_postmeta.meta_value != '1' ) ) AND wp_posts.post_type = 'page' AND ((wp_posts.post_status = 'publish' OR wp_posts.post_status = 'inherit')) AND wp_posts.post_mime_type != image/jpeg GROUP BY wp_posts.ID ORDER BY wp_posts.post_title LIKE '%coron%' DESC, wp_posts.post_date DESC LIMIT 0, 20

WordPress database error: [Not unique table/alias: 'wp_postmeta']
SELECT wp_posts.* FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id WHERE 1=1 AND wp_posts.post_name IN ('search') AND wp_posts.ID NOT IN (4440,4436) AND ( 0 = 1 ) AND ( ( wp_postmeta.meta_key = 'hide_from_search_results' AND wp_postmeta.meta_value != '1' ) ) AND wp_posts.post_type = 'page' AND ((wp_posts.post_status = 'publish' OR wp_posts.post_status = 'inherit')) AND wp_posts.post_mime_type != image/jpeg GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC

Alternatively I have tried adding this whithin my posts_where function

$where .= ' AND (' . $wpdb-postmeta . '.meta_key != hide_from_search_results) OR (' . $wpdb-postmeta . '.meta_key == hide_from_search_results AND ' . $wpdb-postmeta . '.meta_value == 1)';

But get:

WordPress database error: [You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '== hide_from_search_results AND wp_postmeta.meta_value == 1) AND wp_posts.po' at line 1]
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id WHERE 1=1 AND wp_posts.ID NOT IN (4440,4436) AND (((wp_posts.post_title LIKE '%coron%') OR (wp_postmeta.meta_value LIKE '%coron%') OR (wp_posts.post_excerpt LIKE '%coron%') OR (wp_posts.post_content LIKE '%coron%'))) AND wp_posts.post_type = 'page' AND ((wp_posts.post_status = 'publish' OR wp_posts.post_status = 'inherit')) AND (wp_postmeta.meta_key != hide_from_search_results) OR (wp_postmeta.meta_key == hide_from_search_results AND wp_postmeta.meta_value == 1) AND wp_posts.post_mime_type != image/jpeg GROUP BY wp_posts.ID ORDER BY wp_posts.post_title LIKE '%coron%' DESC, wp_posts.post_date DESC LIMIT 0, 20

WordPress database error: [You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '== hide_from_search_results AND wp_postmeta.meta_value == 1) AND wp_posts.po' at line 3]
SELECT wp_posts.* FROM wp_posts LEFT JOIN wp_postmeta ON wp_posts.ID = wp_postmeta.post_id WHERE 1=1 AND wp_posts.post_name IN ('search') AND wp_posts.ID NOT IN (4440,4436) AND ( 0 = 1 ) AND wp_posts.post_type = 'page' AND ((wp_posts.post_status = 'publish' OR wp_posts.post_status = 'inherit')) AND (wp_postmeta.meta_key != hide_from_search_results) OR (wp_postmeta.meta_key == hide_from_search_results AND wp_postmeta.meta_value == 1) AND wp_posts.post_mime_type != image/jpeg GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC

Topic posts-where pre-get-posts filters Wordpress search

Category Web

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.