0

I'm trying to figure out how to loosen up a custom meta field matching string search in a custom search.

Basically, if the meta field of a custom post has "Whistler Bike Park, Canada" and I enter that, I will get the post returned in the search. But if I enter just "Whistler", then I get nothing.

The key line I believe needs editing looks like this:

$where .= " OR (( $wpdb->postmeta.meta_key = '$meta_key' AND $wpdb->postmeta.meta_value = '$meta_value' ))";

Here is the full pre_get_post() hook.

add_action('pre_get_posts', 'site_search_query');
function site_search_query( $query ) 
{
    if (!is_admin() && $query->is_main_query() ) :

        if ( $query->is_search ) :

            // if just a normal search and no in spanish - return 
            // we need to make exception for normal search and is spanish for spanish titles
            // since those are meta values
            if( ( count($_GET) == 1 ) && ( ICL_LANGUAGE_CODE != "es" ) )
                return;

            $s = preg_replace( "/[^a-zA-Z0-9\s]/", "", $_GET['s'] ); // sanitize and get search string;

            unset( $_GET['s'] );
            $params = array();

            foreach( $_GET as $key => $param ) :

                $params[$key] = preg_replace( "/[^a-z0-9.]+/i", "", $param );

            endforeach;

            $meta_queries = array();

            foreach( $params as $param ) :

                switch( $param ) :

                    case 'org':
                        $param = 'organization';
                    break;

                    case 'desc':
                        $param = 'basic_info_long_description_in_english';
                    break;

                endswitch;

                $args = array(
                        'key' => $param,
                        'value' => $s,
                        'compare' => 'LIKE'
                    );

                array_push( $meta_queries, $args );

            endforeach;

            $query->set( 'post_type', 'project' );
            $query->set( 'meta_query', array( $args ) );

            /**
             *  Apparently this is a hack to allow for search by post meta in meta_query for pre_get_post $query->set()
             *  See: http://wpthemetutorial.com/2014/07/17/using-pre_get_posts-meta_query/
             *  this is done as an anonymous function so we can pass it local vars

             *  @param string
             *  @param complex array
             *  @param function
             *  @return string
             */
            $custom_filter = function( $where = '' ) use( $meta_queries, $custom_filter ) 
            {

                global $wpdb;

                foreach( $meta_queries as $meta_query ) :

                    $meta_key = $meta_query['key'];
                    $meta_value = $meta_query['value'];

                    // too restrictive
                    $where .= " OR (( $wpdb->postmeta.meta_key = '$meta_key' AND $wpdb->postmeta.meta_value = '$meta_value' ))";

                    // too loose
                    //$where .= " OR (( $wpdb->postmeta.meta_key = '$meta_key' ))";

                endforeach;

                remove_filter( 'posts_where', $custom_filter );

                return $where;

            };

            add_filter( 'posts_where', $custom_filter );

        endif; // is_search

    endif; // is not admin && is main query

} // site_search_query

Any suggestions welcome.

0

Seems I have an answer - it was how the SQL statement was setup.

$where .= " OR (( $wpdb->postmeta.meta_key = '$meta_key' AND (UPPER($wpdb->postmeta.meta_value) LIKE '%$meta_value%') ))";

Now is the field has the string "Whistler Bike Park, Canada" but the user only searches for "Whistler", I get the post/s returned that I expect.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.