Forums Forums Search & Filter Pro Filter based on range of meta data values

Viewing 10 posts - 1 through 10 (of 10 total)
  • Anonymous
    #9823

    All of my posts have two custom meta fields: $field_A and $field_B. I’m needing to build a functionality where a user can input a value, say $value, and then only posts where $value lies in between field_A and field_B are shown. That is, I need to display posts where $field_A < $value < $field_B is true.

    From what I can see S&F pro doesn’t do this out of the package. Is there a relatively simple way of modifying the code so that I can do this? Is there a particular file I should be looking at if I want to try and implement this myself?

    Thanks in advance,
    Dan

    Anonymous
    #9873

    I’ve found that I can add the following lines to class-search-filter-get-results.php to get the results that I need.

    $args['meta_query'][] = array('key'=>'field_A', 'value' => $value, 'type'=>'NUMERIC', 'compare' => '<=');
    $args['meta_query'][] = array('key'=>'field_B', 'value' => $value, 'type'=>'NUMERIC', 'compare' => '>=');

    Obviously this is a very hacked-together solution and not necessarily the solution that I want to land on. It maybe helps to demonstrate what I’m trying to achieve, however I’d still like to be able to include inputs in the search from so that the user can specify the value of $value. Although I’m not an expert, I’m relatively comfortable using PHP, so I don’t really need a full solution that modifies the admin interface – I am happy editing code if I know where I should be looking.

    Ross Moderator
    #9969

    Hey Daniel

    I think I follow you – I had another user request something similiar.

    Basically they would have a range slider, where the bottom was compared against a specific meta key, and the top end was compared against another – is this the kind of thing you are talking about?

    PS what line number do you insert the above code at?

    Thanks

    Anonymous
    #9976

    Hi Ross, thanks for the reply.

    A range slider where the top and bottom numbers are compared against two different meta keys would work, however even simpler would be a simple single-value input field (text input? Drop down? etc.) where the single input is compared to two different meta keys.

    What I am essentially trying to do is create an “opening hours” search for a bunch of restaurants. Each of my “restaurant” posts has an “open time” meta field and a “close time” meta field. Basically I want to be able to filter by displaying only restaurants that are open at a given time.

    I inserted the above code at 95 (just above the $query = new WP_Query($args) line). Though this was more just for me to play around with the $args input to WP_query to help me understand what I can do with it (I have a little experience with PHP and WordPress, but not much). I have since removed the lines because it’s not a permanent solution.

    Ross Moderator
    #9979

    Ah ok… I can see loads of potential in adding this kind of functionality to the plugin, you use a single input, or range slider, or all sorts of kinds of fields for numbers and comparing against 2 meta fields for upper and lower limits – this is pretty tricky even as a hack, but I’ll give it a go:

    So lets go with a drop down (as it already exists) – so add a post meta field to the search form UI, choose the type “choice” and create a dropdown with the values you want available.

    Next – head back to “class-search-filter-get-results.php”

    Head to line 570 with the function filter_meta_query_where. Because we have a choice field type this meta query will get be added to the query here:

    else if($meta_query['type']=="value") (line 602)

    What I would do is do a check for the meta field you set in S&F admin, and run some custom code instead… so this:

    else if($meta_query['type']=="value")
    {
    	$where .= " AND ((sf_meta_$meta_iter.meta_key = '".$meta_query['key']."' AND (";
    	
    	$meta_val_arr = array();
    	
    	foreach($meta_query['values'] as $value)
    	{
    		array_push($meta_val_arr, "sf_meta_$meta_iter.meta_value = '$value'");
    	}
    	
    	$where .= implode(" ".$meta_query['operator']." ", $meta_val_arr);
    	
    	$where .= ")))";
    }

    would be this:

    else if($meta_query['type']=="value")
    {
    	if($meta_query['key']=="SOME_KEY_NAME") //this will be the meta key you have chosen in your post meta field
    	{
    		$value = (int)$value; //cast value as a number
    		
    		//this part says - if the meta is under or equal to the value of the user input - so the field you choose in your post meta field, should be the closing time
    		$where .= " AND ((sf_meta_$meta_iter.meta_key = '".$meta_query['key']."')";
    		$where .= " AND (sf_meta_$meta_iter.meta_value <= $value))"
    		
    		//this part says - if the meta second meta key (entered manually here) is over or equal to the value of the user input
    		$where .= " AND ((sf_meta_$meta_iter.meta_key = 'SECOND_META KEY')";
    		$where .= " AND (sf_meta_$meta_iter.meta_value >= $value))"
    	}
    	else
    	{
    		$where .= " AND ((sf_meta_$meta_iter.meta_key = '".$meta_query['key']."' AND (";
    	
    		$meta_val_arr = array();
    	
    		foreach($meta_query['values'] as $value)
    		{
    			array_push($meta_val_arr, "sf_meta_$meta_iter.meta_value = '$value'");
    		}
    	
    		$where .= implode(" ".$meta_query['operator']." ", $meta_val_arr);
    	
    		$where .= ")))";
    	}
    }

    The query itself is just an SQL WHERE clause… you should be able to tell and its just added to a string $where for running later on in WP.

    Copy and paste that new code above in an editor so you can read the comments properly – I think its pretty close to what you want as a hack just requires some tweaks from you ๐Ÿ˜‰

    Good luck!

    Anonymous
    #9981

    Thanks so much for that Ross – I really appreciate your great customer service! I am about to head off to work so I’ll have to wait until later this evening to give this a shot, but it gives me a great place to start. I’ll let you know how it goes! ๐Ÿ™‚

    Ross Moderator
    #9982

    Well see you on the other side, its nearly bed time for me ๐Ÿ˜‰

    Anonymous
    #10026

    Ok I’ve been playing around with the code you provided – it has been very helpful, both in terms of getting me to a workable solution, but also in helping me understand more about how the plugin works ๐Ÿ™‚

    A couple of questions and comments:

    1. On the line $value = (int)$value; //cast value as a number it seems that $value is empty, because it is outside of the foreach loop where it takes values of $meta_query['values']. I’ve changed it to $value = (int)$meta_queries['values'][0]; and it seems to work.
    2. Looks like there are a couple of lines without a terminating semicolon (;). Easy fix ๐Ÿ™‚
    3. QUESTION: I’m a little confused about the sf_meta_$meta_iter.meta_key part. With the code as you’ve written, the $where SQL clause ends up looking like the following I’ve shortened it to just show the relevant part:
      $where = "...AND ((sf_meta_1.meta_key = 'open_time') AND (sf_meta_1.meta_value <= $user_input_time))
       AND ((sf_meta_1.meta_key = 'close_time') AND (sf_meta_1.meta_value >= $user_input_time))"

      It looks like sf_meta_1.meta_key is being checked against both the “open time” and “close time” meta keys. Obviously it can’t be equal to both meta keys at the same time, so I found that the search would always return no results. Does this make sense? Is there an easy way to resolve this?

    Thanks again,
    Dan

    Ross Moderator
    #10080

    Yup I follow you – its a bit out of support figuring this out but if I get a chance I’ll have another play and see what I can do ๐Ÿ™‚

    Anonymous
    #10086

    Yep I understand, and I appreciate the help you’ve already provided! ๐Ÿ™‚ I’ve managed to put together a working solution that allows users to select, independently, a day and a time, and then the plugin shows restaurants that are open at that day and time. Until I properly learn how to use ajax to build my own plugin, this will do ๐Ÿ™‚

Viewing 10 posts - 1 through 10 (of 10 total)