Skip Navigation

[Resolved] Filter posts via comparing field numeric value – 3 checkboxes filtering options

This thread is resolved. Here is a description of the problem and solution.

Problem:
Client has a numeric custom field used as a filter in a View, but wants to present the filter as three checkboxes for ranges (i.e. less than x, more than y, between x and y), while still being able to use other filters on the same View.

Solution:
This requires custom code.

See below for the proposed solution, which is particular to this site but which can be adapted as required:

https://toolset.com/forums/topic/filter-posts-via-comparing-field-numeric-value-3-checkboxes-filtering-options/#post-624557

This support ticket is created 6 years, 1 month 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
- 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 -
- 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 -

Supporter timezone: Europe/London (GMT+01:00)

This topic contains 9 replies, has 2 voices.

Last updated by hendrikH 6 years, 1 month ago.

Assisted by: Nigel.

Author
Posts
#620025
example.jpg

What i am trying to do:
I have 2 post types "Individual bike tours" and "Guided bike tours". Both of there post types have separate custom fields (text field) called "Metres of Elevation Individual Tour" and "Metres of Elevation Guided Tour". Those fields are populated with a numbers representing *meters*.

I am trying to filter those posts like this with 3 checkboxes:
If the value of the field is less than 200
If the value of the field is between 200-500
If the value of the field is greater than 500

My goal is to make the filter work without the need to manually check an additional taxomony.
Is there a way to automatically fit the post in a certain taxonomy based on the value of one field?

I have followed the Toolset documentation. The filters currently work but in addition of the field value, i have to check one taxonomy term.

The link to the site:
hidden link

#620097

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Screen Shot 2018-02-27 at 13.42.28.png

Hi Hendrick

If you have one custom field—e.g. "metres of elevation"—then you can have one filter for that field, e.g. "less than the value entered".

To do what you are looking to do, have a dropdown with 3 options, below 200 metres, between 200-500 metres, and above 500 metres, you are going to need to manipulate the query using wpv_filter_query according to what the user selects.

So you will first need to add the filter in such a way that it is displayed as a select dropdown using some placeholder values that you will test for in your PHP code, as shown in the screenshot where each case has a value of 1, 2, or 3.

A minor gotcha when you come to insert the View filter is that you need to manually set the Custom Search Settings so that it Always shows all values for inputs.

Then you need to add code that hooks into wpv_filter_query to modify the meta_query according to what was selected by the user.

I would encourage you to do this yourself, though if you are adding several filters and not just this one (which I think you are) it is a little tricky, so let me suggest the following code to you. Please read through it and try to understand it, the key part being switch case to modify the meta_query arguments depending on the submitted filter value.

You will need to edit the slug of your custom field and the View id. The following also supposes that your select field values are 1, 2, and 3 as per the screenshot.

/**
 * Custom filter by height
 */
function tssupp_filter_thing_by_height( $query_args, $view_settings, $view_id ){

    if ( 152 == $view_id && isset( $query_args['meta_query'] ) ) {

        foreach( (array)$query_args['meta_query'] as $k=>$v ){

            if ( isset( $v['key'] ) && $v['key'] == 'wpcf-height' ) {

            	switch ( $v['value'] ) {
            		case 1:
            			$query_args['meta_query'][$k]['value'] = 200;
            			$query_args['meta_query'][$k]['type'] = 'numeric';
            			$query_args['meta_query'][$k]['compare'] = '<=';
            			break;
            		case 2:
            			$query_args['meta_query'][$k]['value'] = array( 200, 500 );
            			$query_args['meta_query'][$k]['type'] = 'numeric';
            			$query_args['meta_query'][$k]['compare'] = 'BETWEEN';
            			break;
            		case 3:
            			$query_args['meta_query'][$k]['value'] = 500;
            			$query_args['meta_query'][$k]['type'] = 'numeric';
            			$query_args['meta_query'][$k]['compare'] = '>=';
            			break;
            	}
            }
        }
	}

	return $query_args;
}
add_filter('wpv_filter_query', 'tssupp_filter_thing_by_height', 101, 3);

Please note that providing custom code and supporting it is outside our support policy and I provide the above to get you started rather than as a tested solution.

#621582
Untitled.jpg

Hello Nigel and thank you very much for the custom code provided. It worked you beautiful.
I've implamented the code for length, height and difficulty.
Because the design is done is such a way, i had to replace the dropdown for radios. But the result was the same.
Now...doing so the flexibility of the filters diminished. I've tried using checkboxes (the ideal scenario for using AND condition) but despite the fact that the filter query updates with a "&" between the metas, they are always queried in the same order (1,2,3) and the result is displayed only for the first query.
Anything comes to mind which can help me with this?
Thank you.

#621992

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Hendrik

What does the final query look like?

Just before you return $query_args, if you send them to your debug log with error_log(print_r($query_args, true)); what do the final arguments look like?

#622207
support-img.jpg

Hello Nigel,
I've added the error_log to the function but i get nothin in the console. Maybe i'm doing something wrong.
I've attached a image. This is how my url looks like when i try to use checkboxes. In this case all 3 checkboxes for length are checked.
Thank you.

#622489

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Hendrik

It won't show in the console, that is for JavaScript, it will show in your PHP logs.

If you haven't already, turn on the debug log by editing your wp-config.php file and change the line with WP_DEBUG like so:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

That will create a debug.log file in your wp-content directory which you can examine in any text editor.

Now when you load the page with that View anything you error_log will be sent to that debug.log file.

So editing my example code above you would log the query args like so:

/**
 * Custom filter by height
 */
function tssupp_filter_thing_by_height( $query_args, $view_settings, $view_id ){
 
    if ( 152 == $view_id && isset( $query_args['meta_query'] ) ) {
 
        foreach( (array)$query_args['meta_query'] as $k=>$v ){
 
            if ( isset( $v['key'] ) && $v['key'] == 'wpcf-height' ) {
 
                switch ( $v['value'] ) {
                    case 1:
                        $query_args['meta_query'][$k]['value'] = 200;
                        $query_args['meta_query'][$k]['type'] = 'numeric';
                        $query_args['meta_query'][$k]['compare'] = '<=';
                        break;
                    case 2:
                        $query_args['meta_query'][$k]['value'] = array( 200, 500 );
                        $query_args['meta_query'][$k]['type'] = 'numeric';
                        $query_args['meta_query'][$k]['compare'] = 'BETWEEN';
                        break;
                    case 3:
                        $query_args['meta_query'][$k]['value'] = 500;
                        $query_args['meta_query'][$k]['type'] = 'numeric';
                        $query_args['meta_query'][$k]['compare'] = '>=';
                        break;
                }
            }
        }
        error_log(print_r($query_args, true));
    }
 
    return $query_args;
}
add_filter('wpv_filter_query', 'tssupp_filter_thing_by_height', 101, 3);

Now, we started out talking about a select field, then you said it was done as a radio field, and in your last update you said checkboxes.

Can you clarify what we are working with?

#623740

Hello Nigel,
To clarify, the current code (the code you provided) works great with radios, it filters accordingly.

I've also tried to use it with checkboxes, because that's the ideal scenario that i am looking for. Being able to select multiple heights options. But despite the fact that the filter query updates with a "&" between the metas, they are always queried in the same order (1,2,3) and the result is displayed only for the first query.

I attach the debug log using height filters - with radios in one situation and with the checkboxes in the second situation.

USING FUNCTIONAL RADIOS

[09-Mar-2018 14:56:02 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

[09-Mar-2018 14:56:35 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [1] => Array
                (
                    [key] => wpcf-height-meter
                    [value] => 500
                    [type] => numeric
                    [compare] => >=
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

[09-Mar-2018 14:56:40 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [1] => Array
                (
                    [key] => wpcf-height-meter
                    [value] => Array
                        (
                            [0] => 200
                            [1] => 500
                        )

                    [type] => numeric
                    [compare] => BETWEEN
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

[09-Mar-2018 14:56:47 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [1] => Array
                (
                    [key] => wpcf-height-meter
                    [value] => 200
                    [type] => numeric
                    [compare] => <
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

USING NON FUNCTIONAL CHECKBOXES


[09-Mar-2018 15:04:07 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

[09-Mar-2018 15:04:11 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

[09-Mar-2018 15:04:17 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [1] => Array
                (
                    [key] => wpcf-height-meter
                    [value] => 200
                    [type] => numeric
                    [compare] => <
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

[09-Mar-2018 15:04:21 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [1] => Array
                (
                    [key] => wpcf-height-meter
                    [value] => 200
                    [type] => numeric
                    [compare] => <
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

[09-Mar-2018 15:04:26 UTC] Array
(
    [post_type] => Array
        (
            [0] => individual-bike-tour
            [1] => guided-bike-tour
        )

    [paged] => 1
    [suppress_filters] => 
    [ignore_sticky_posts] => 1
    [posts_per_page] => -1
    [post__not_in] => Array
        (
            [0] => 22
        )

    [wpv_original_limit] => -1
    [wpv_original_offset] => 0
    [wpv_original_posts_per_page] => -1
    [meta_query] => Array
        (
            [0] => Array
                (
                    [key] => wpcf-show-tour
                    [value] => 1
                    [type] => CHAR
                    [compare] => =
                )

            [1] => Array
                (
                    [key] => wpcf-height-meter
                    [value] => 200
                    [type] => numeric
                    [compare] => <
                )

            [relation] => AND
        )

    [post_status] => Array
        (
            [0] => publish
            [1] => private
        )

    [orderby] => date
    [order] => DESC
)

Thank you for your time.

#624246

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Hendrik

Thanks for that, I understand the issue now. The code I proposed was intended for/expected a single selection for the height option.

I'll need some time to think about a solution to handle multiple selections. I'll get back to it a little later when I have gone through some of the other tickets in the queue.

#624557

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi Hendrik

I updated the code on my test site to allow for making multiple selections with checkboxes, while also including other filters in the search form, see below.

It was a fun exercise for me but please note that providing code such as this falls very much outside of our support policies, so if you have problems implementing it I won't be able to support it.

/**
 * Custom filter by height
 */
function tssupp_filter_thing_by_height( $query_args, $view_settings, $view_id ){

	$field = 'wpcf-height';

    if ( 152 == $view_id && isset( $query_args['meta_query'] ) ) {

        foreach( (array)$query_args['meta_query'] as $k=>$v ){

            if ( isset( $v['key'] ) && $v['key'] == $field ) {

            	$values = explode( ",", $v['value'] );

            	$query_args['meta_query'][$k] = array( 'relation' => 'OR' );

				if ( in_array( "1", $values ) ) {
					$query_args['meta_query'][$k][] = array(
						'key'		=>	$field,
						'value'		=>	200,
						'type'		=>	'numeric',
						'compare'	=>	'<='

					);
				}

				if ( in_array( "2", $values ) ) {
					$query_args['meta_query'][$k][] = array(
						'key'		=>	$field,
						'value'		=>	array( 200, 500 ),
						'type'		=>	'numeric',
						'compare'	=>	'BETWEEN'
					);
				}

				if ( in_array( "3", $values ) ) {
					$query_args['meta_query'][$k][] = array(
						'key'		=>	$field,
						'value'		=>	500,
						'type'		=>	'numeric',
						'compare'	=>	'>='

					);
				}
            }
        }
	}
	return $query_args;
}
add_filter('wpv_filter_query', 'tssupp_filter_thing_by_height', 101, 3);
#624790

Thank you very much Nigel!
The code worked out very well. I've understood the code you writted, but was very unlikely that I would have been able to come with a solution by myself.

Best regards.

This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.