Skip Navigation

[Resolved] build absolute search on two custom fields

This support ticket is created 4 years, 2 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 - - 9:00 – 13:00
14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 - - 14:00 – 18:00

Supporter timezone: Africa/Casablanca (GMT+01:00)

This topic contains 8 replies, has 2 voices.

Last updated by andrewF-6 4 years, 2 months ago.

Assisted by: Jamal.

Author
Posts
#1813655

I have a page with a Search Form searching against a Custom Post type on two fields - "Surname" and "Card Number". My search form is returning the results on the same page via AJAX and it must perform an EXACT Match Search against BOTH fields. Only ONE result should ever be returned. If no data is entered, NO results should be returned:

Two things are not happening the way I want - the search results are not exact match, the search is not being conducted against BOTH fields as an AND but rather against either field as an EITHER / OR, the search is returning more than one result which it should only ever return 1 result, and if I click submit with empty search fields it returns all results instead of NO results:
1) If I leave the search form blank and click SUBMIT, ALL custom post type posts are displayed; I would like the search to not return ANY results if NO search terms are entered or WRONG search terms are entered.
2) I am searching against TWO custom post type fields but the search form displays results that satisfy either of the fields; I need the search form to perform an EXACT MATCH against BOTH fields. Both fields must be required and the search form should return results that are an EXACT MATCH.
3) Only 1 Result should be returned per search query in the Ajax result display. It should never return more than one result since the Card Number search field is unique.

I built this search using Toolset Blocks and not Toolset Views Search. The results content template is built using Toolset Blocks.

#1813859

When one of the custom fields did not have a value for the search filter, it does not get passed to the view's query. So, we must make sure that the view's query has both fields in its meta_query. The following code should work, and will also reset the views if none of the custom fields were added:

add_filter( 'wpv_filter_query', 'query_have_two_cf', 30, 3 );
function query_have_two_cf( $query_args, $view_settings, $view_id ) {
	// Execute this code only for my view id(1173)
	$my_view_id = 1718;
	$first_field = 'wpcf-book-status';
	$second_field = 'wpcf-number-of-pages';
	
	if ( $view_id == $my_view_id ) {
		// If no custom fields
		if ( !isset( $query_args['meta_query'] ) ) {
			$query_args['post__in'] = array(0);
			return $query_args;
		}
		
		// must contain both fields
		if ( my_contains_function( $query_args['meta_query'], $first_field ) && my_contains_function( $query_args['meta_query'], $second_field ) ) {
			$query_args['meta_query']['relation'] = 'AND';
		} else {
			$query_args['post__in'] = array(0);
		}
		
		$query_args['meta_query']['relation'] = 'AND';
	}

	// return the query arguments
	return $query_args;
}

Please adapt the following lines to your website:

	$my_view_id = 1718;
	$first_field = 'wpcf-book-status';
	$second_field = 'wpcf-number-of-pages';

You can find the view id in the browser console. Check this screenshot hidden link
For fields, you need to append the field's slug to the Toolset prefix 'wpcf-'. Check this screenshot from my test site hidden link

Let me know what you will get.

#1813937
Validate-IHANA-Lifestyle - validate code.png

Hi Jamal,

Unfortunately I just get a spinning icon - it never ends.

This is the exact code I used:

<?php
/**
 * New custom code snippet (replace this with snippet description).
 */

toolset_snippet_security_check() or die( 'Direct access is not allowed' );

// Put the code of your snippet below this comment.

add_filter( 'wpv_filter_query', 'query_have_two_cf', 30, 3 );
function query_have_two_cf( $query_args, $view_settings, $view_id ) {
    // Execute this code only for my view id(120428)
    $my_view_id = 120428;
    $first_field = 'wpcf-surname';
    $second_field = 'wpcf-card-number';
     
    if ( $view_id == $my_view_id ) {
        // If no custom fields
        if ( !isset( $query_args['meta_query'] ) ) {
            $query_args['post__in'] = array(0);
            return $query_args;
        }
         
        // must contain both fields
        if ( my_contains_function( $query_args['meta_query'], $first_field ) && my_contains_function( $query_args['meta_query'], $second_field ) ) {
            $query_args['meta_query']['relation'] = 'AND';
        } else {
            $query_args['post__in'] = array(0);
        }
         
        $query_args['meta_query']['relation'] = 'AND';
    }
 
    // return the query arguments
    return $query_args;
}
#1813977

would you allow me temporary access to your site to check this further? Or provide a Duplicator copy of your website and I'll check it locally.
Your next reply will be private to let you share credentials or download links safely.

I will need to know what view?
What URL on the frontend?

#1814025

Hi there...

Where do you define my_contains_function?

Even when I pass the URL:
hidden link

It doesn't return any data whereas if I turn off the code snippet this URL returns the exact screen I am looking for

#1814035

My apologies, I forgot the share it, the full code

function my_contains_function( $meta_query, $field ) {
	foreach( $meta_query as $meta ){
		if ( isset( $meta['key'] ) && ( $meta['key'] == $field ) )
			return true;
	}
	
	return false;
}
#1814085

Thanks Jamal,

Where do I put this code?

The order and indents matter.

Thanks

#1814133

You can put it before or after the previous code:

<?php
/**
 * New custom code snippet (replace this with snippet description).
 */
 
toolset_snippet_security_check() or die( 'Direct access is not allowed' );
 
// Put the code of your snippet below this comment.

function my_contains_function( $meta_query, $field ) {
    foreach( $meta_query as $meta ){
        if ( isset( $meta['key'] ) && ( $meta['key'] == $field ) )
            return true;
    }
     
    return false;
}
 
add_filter( 'wpv_filter_query', 'query_have_two_cf', 30, 3 );
function query_have_two_cf( $query_args, $view_settings, $view_id ) {
    // Execute this code only for my view id(120428)
    $my_view_id = 120428;
    $first_field = 'wpcf-surname';
    $second_field = 'wpcf-card-number';
      
    if ( $view_id == $my_view_id ) {
        // If no custom fields
        if ( !isset( $query_args['meta_query'] ) ) {
            $query_args['post__in'] = array(0);
            return $query_args;
        }
          
        // must contain both fields
        if ( my_contains_function( $query_args['meta_query'], $first_field ) && my_contains_function( $query_args['meta_query'], $second_field ) ) {
            $query_args['meta_query']['relation'] = 'AND';
        } else {
            $query_args['post__in'] = array(0);
        }
          
        $query_args['meta_query']['relation'] = 'AND';
    }
  
    // return the query arguments
    return $query_args;
}

Indentation won't matter 🙂

#1814151

My issue is resolved now. Thank you!

This was a tough one but I am grateful!