WordPress.org

Forums

[resolved] Category sidebar seach: checkbox and custom fields problem (29 posts)

  1. edow
    Member
    Posted 1 year ago #

    Hi,

    I'm struggling with the following problem for a while. It's almost working, but still not yet. First of all, sorry for my bad English.

    I made this sidebar search form (see code below) for my category page to filter the search results based on the tags which are available within the category.

    The first part is working great when I use radio buttons, but I want the form to remember mulitple checkbox fields. Someone suggested name="tag[]" but that's not working unfortunately. When I use name="tag" the url output is /?tag=test&tag=test2 instead of /?tag=test,test2 so it won't work properly.

    The next problem. I use this function to make a url parameter based on a custom field, but I can't figure out how to use it with multiple keys.

    function wpa_filter_home_query( $query ){
        if( $query->is_main_query()
        && isset( $_GET['provincie'] ) ) {
            $meta_query = array(
                array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'])
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    }
    add_action( 'pre_get_posts', 'wpa_filter_home_query' );

    And the last problem is that I want to show only keys from custom fields under <h3>Land</h3> and <h3>Regio</h3> just like the code only shows tags which are used. I also can't figure out how to let this work for the custom fields.

    The form:

    <form name="tags" onChange="document.forms.tags.submit();">
    		<?php
    		if (is_category()){
    		  $cat = get_query_var('cat');
    		  $yourcat = get_category ($cat);
    		}
    		$tag_IDs = array();
    		query_posts('category_name='.$yourcat->slug);
    		if (have_posts()) : while (have_posts()) : the_post();
    		  $posttags = get_the_tags();
    		  if ($posttags):
    			foreach($posttags as $tag) {
    			if (!in_array($tag->term_id , $tag_IDs)):
    			   $tag_IDs[] = $tag->term_id;
    			   $tag_names[$tag->term_id] = $tag->name;
    			   $tag_slug[$tag->term_id] = $tag->slug;
    			 endif;
    			}
    		  endif;
    		endwhile; endif;
    		wp_reset_query();
    
    		if (!empty($tag_IDs)){
    			echo '<h3>Het meest geschikt voor</h3>';
    			echo "<input type=\"checkbox\" name=\"tag\" value=\"\"> Show all<br>";
    		}
    		foreach($tag_IDs as $tag_ID){
    			$checked = $tag_slug[$tag_ID];
    			echo '<input type="checkbox" name="tag" value="'.$checked.'"' ;
    			if((isset($_GET["tag"])) && $_GET["tag"] == $checked) {
    			echo ' checked="checked"';
    			}
    			echo '> '.$tag_names[$tag_ID].'<br>';
    		}
    		?>
    
    		<div class="margin25px"></div>
    
    		<h3>Land</h3>
    			<input type="radio" name="land" value=""> Alles weergeven<br>
    			<input type="radio" name="land" value="nederland" <?php if((isset($_GET["land"])) && $_GET["land"] == "nederland") { echo "checked";}?>> Nederland<br>
    			<input type="radio" name="land" value="belgie" <?php if((isset($_GET["land"])) && $_GET["land"] == "belgie") { echo "checked";}?>> Belgie
    
    		<div class="margin25px"></div>
    
    		<h3>Regio</h3>
    			<input type="radio" name="provincie" value=""> Alles weergeven<br>
    			<input type="radio" name="provincie" value="gelderland" <?php if((isset($_GET["provincie"])) && $_GET["provincie"] == "gelderland") { echo "checked";}?>> Gelderland<br>
    			<input type="radio" name="provincie" value="overijssel" <?php if((isset($_GET["provincie"])) && $_GET["provincie"] == "overijssel") { echo "checked";}?>> Overijssel
    		</form>

    Hopefully someone can give me some hints to make this work. It's a great category search form if it's working properly. Sorry if I ask to many questions, but it's all related to each other since it's all meant to make the sidebar filter function work.

  2. bcworkz
    Member
    Posted 1 year ago #

    Hello my friend! So many questions today :) Er, yesterday by now.

    To get multiple checkbox values, you must use '[]' as the final part of the name, that was good advice. I don't know why it's not working, but the '[]' must occur for there to be any hope of working.

    If the checkboxes are all named "tag[]" and the form method is GET, the URL parameters will be something like ?tag[]=test&tag[]=test2. There is not a way to get forms to structure the request as you suggest like ?tag=test,test2. Though the URL parameter names include the '[]' portion, they are dropped in the $_GET key. You end up with something equivalent to $_GET['tag'] = array('test', 'test2',);. This is the way it happens, your code needs to work with it.

    How you build a query from checkbox values depends if the values are to be related with AND or OR. If OR, set the 'value' as the $_GET['tag'] array and set the 'compare' as 'IN'. If AND, you must step through the checkbox values with foreach(){} and build an array of arrays for 'meta_query' where each 'value' is a single checkbox value so all the arrays together have a relation of 'AND'.

    There is no easy answer to get custom fields that are actually used because they are in post_meta and not part of a taxonomy like tags and categories. You need to query for all candidate posts from which to check for fields. Then step through the posts and and accumulate unique fields into an array. You can use if ( !in_array( $value, $fields )) $fields[] = $value; to only add values that do not currently exist so that all values are unique.

    I hope that answers your questions, if not, you know the routine :)

  3. edow
    Member
    Posted 1 year ago #

    Thanks for your help again!

    If I use this code:

    foreach($tag_IDs as $tag_ID){
    			$checked = $tag_slug[$tag_ID];
    			echo '<input type="checkbox" name="tag[]" value="'.$checked.'"' ;
    			if((isset($_GET["tag"])) && $_GET["tag"] == $checked) {
    			echo ' checked="checked"';
    			}
    			echo '> '.$tag_names[$tag_ID].'<br>';
    		}

    I get this url paramter:

    /?tag%5B%5D=test

    and then there're no search results. Also the checkboxes aren't checked anymore.

    When I have more time I'll look after your other answers and post my results here.

  4. edow
    Member
    Posted 1 year ago #

    I think I have the solution for the creating of the url paramter based on multiple custom fields. It looks like this code is working fine:

    function wpa_filter_home_query( $query ){
        if( $query->is_main_query()
    	&& isset( $_GET['land'] )
        && isset( $_GET['provincie'] ) ) {
            $meta_query = array(
                array(
                    'key' => 'land',
                    'value' => array( $_GET['land'])
                ),
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'])
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    }
    add_action( 'pre_get_posts', 'wpa_filter_home_query' );

    It's another approach then you suggested, but I thought I'll give it a try.

  5. bcworkz
    Member
    Posted 1 year ago #

    Sure, anything is worth a try :)

    My problem is I don't know exactly how you want the checkbox selections to influence the query. If your last example represents what you want, then that is what you need to use. What it does is only return posts with both land and provincie terms, but the returned posts can have any of the checked terms assigned. I can imagine this is very likely what you want, so kudos for developing that!

  6. edow
    Member
    Posted 1 year ago #

    I see I didn't test it well enough. It looks like it only works when "land" and "provincie" are both checked, just like you said. Then it is filtering the post whith a specific "land" AND "provincie" (also when a tag is checked). But when I only check "land" or "provincie" (even when a tag is checked) it isn't filtering (only the checked tag is).

    So, if I check one tag it works. But if I only check "land" or "provincie" the query isn't filtering. I need it to work all together (that is already working), but also everything separately.

    'compare' => 'IN' isn't working either. I'm not sure how to use the AND function yet, but I'll give it a try.

    This it how it looks like (without any checkes): http://oi58.tinypic.com/2wp05km.jpg.
    The url parameter then is (if I check it): /?tag=test&land=nederland&provincie=overijssel (this works).

    But when it is /?land=nederland OR /?provincie=gelderland it isn't working.

    So, when "land" and "provincie" are filtering independently it should work, but right now they're filtering when one another or a tag is checked.

  7. edow
    Member
    Posted 1 year ago #

    With one array it works when I click on "provincie" without the need of selecting something else.

    function wpa_filter_home_query( $query ){
        if( $query->is_main_query()
        && isset( $_GET['provincie'] ) ) {
            $meta_query = array(
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'])
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    }
    add_action( 'pre_get_posts', 'wpa_filter_home_query' );
  8. edow
    Member
    Posted 1 year ago #

    About the query from checkbox values: I figured out the relation should be AND. I didn't know exactly what you mean with "If AND, you must step through the checkbox values with foreach(){} and build an array of arrays for 'meta_query' where each 'value' is a single checkbox value so all the arrays together have a relation of 'AND'."

    So, after much struggle I came with my own alternate solution:

    <?php
    function wpa_filter_home_query( $query ){
        if( $query->is_main_query()
        && isset( $_GET['land'] )
    	&& isset( $_GET['provincie'] ) ) {
            $meta_query = array(
    		'relation' => 'AND',
    			array(
                    'key' => 'land',
                    'value' => array( $_GET['land'] )
                ),
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    	elseif( $query->is_main_query()
    	&& isset( $_GET['land'] ) ) {
            $meta_query = array(
    			array(
                    'key' => 'land',
                    'value' => array( $_GET['land'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    	elseif( $query->is_main_query()
    	&& isset( $_GET['provincie'] ) ) {
            $meta_query = array(
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    }
    add_action( 'pre_get_posts', 'wpa_filter_home_query' );
    ?>

    I'm not sure why it's working, but it looks like it is working alright. Is this a proper solution or shouldn't I use it in this way?
    With this code I can also filter on "land" and "provincie" separately.

    If it's alright, then my next problem is that I want to remove the parameter /?land= if I check "Show All". When there's /?land= in the parameter it isn't filtering properly.

  9. bcworkz
    Member
    Posted 1 year ago #

    Sorry to have been ignoring you for the past few days, I've been away.

    What I meant by the phrase you quoted only applies if you want posts where ALL the checked terms for a taxonomy are ALL assigned to every post returned. Since this does not sound like what you want, I will not try to explain further unless you think it's important.

    What you ended up with was exactly what I had in mind while reading your posts from a few days back, so good work figuring that out on your own. Sorry it was such a struggle, but you probably learned more than if I had just told you what to do :)

    I'm not quite sure what the problem with /?land= is with "Show All" but the solution is probably yet another if/elseif condition when "Show All" is checked that builds a query that essentially skips over the meta_query portion entirely, unless maybe you need to require that something be assigned to avoid returning unrelated posts.

  10. edow
    Member
    Posted 1 year ago #

    Hi,

    No problem and I hope you had a nice couple of days off :)

    If /?land= is in the url parameter then zero results are given instead of all the results, so when I click the "Show All" radio button then I need the parameter /?land= to disappear. I'll try what you suggested.

    In the meanwhile another problem occurs :(
    When I'm on page 2 in the category (/page/2/) and I check something a 404 error appears. I found out I need to add the "paged" parameter to the query.
    I thought to do it like this:

    function wpa_filter_home_query( $query ){
    	$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
    	if( $query->is_main_query()
        && isset( $_GET['land'] )
    	&& isset( $_GET['provincie'] ) ) {
    		$meta_query = array(
    		'relation' => 'AND',
    			array(
                    'key' => 'land',
                    'value' => array( $_GET['land'] ),
    				'paged' => $paged
                ),
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'] ),
    				'paged' => $paged
                )
            );
            $query->set( 'meta_query', $meta_query );

    But this still gives a 404 error on page 2 of the category.

    I also tried 'paged' => get_query_var( 'paged' ) but without succes.

    So the form is almost working as I want, but not on page 2, 3 and so on.

  11. bcworkz
    Member
    Posted 1 year ago #

    Arrrgh! If it's not one thing it's another! Such is the nature of coding I suppose :/

    Apparently using query_posts() means you need to manage pagination as part of that query, WP only handles pagination for the original WP_Query object. I'm a little surprised using is_main_query() works for query_posts(), but I've seen similar behavior before.

    The thing is the usual symptom of the need to manage pagination is the first page is returned regardless of the page number requested, not returning a 404. So the problem may lie elsewhere. Just in case, the manage pagination issue is discussed on Making Custom Queries using Offset and Pagination.

    If you were to dump the query object you are modifying, I think you will find 'paged' is defined since it is in the request URL. What may be missing or erroneous is 'posts_per_page'. Setting it from the value in the options table may be all that's required.

    Failing that, the thing to do with unexpected 404s is to output the actual query string used from the 'posts_request' filter. Examining this usually reveals what the problem is. The tricky part is determining what to do to correct the query so it works properly. I might have an idea for what to do once we know what the problem with the query is.

    If you cannot decipher the query string, post it here and I'll try to make sense of it.

  12. edow
    Member
    Posted 1 year ago #

    I tried the code from http://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination as you suggested, but with no luck.

    In functions.php I added 'posts_per_page' => 9, but also without luck.

    The last thing I tried was adding this in functions.php:

    if ( $query->is_main_query()){
    		  $query->set('posts_per_page', 9);
    	  }

    But that isn't working either. Everything is still giving 404 errors on page 2.

    This is my current code:

    In functions.php:

    /* Create URL parameter based on custom field */
    function wpa_filter_home_query( $query ){
    	if( $query->is_main_query()
        && isset( $_GET['land'] )
    	&& isset( $_GET['provincie'] ) ) {
    		$meta_query = array(
    		'relation' => 'AND',
    			array(
                    'key' => 'land',
                    'value' => array( $_GET['land'] )
                ),
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    	elseif( $query->is_main_query()
    	&& isset( $_GET['land'] ) ) {
            $meta_query = array(
    			array(
                    'key' => 'land',
                    'value' => array( $_GET['land'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    	elseif( $query->is_main_query()
    	&& isset( $_GET['provincie'] ) ) {
            $meta_query = array(
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    }
    add_action( 'pre_get_posts', 'wpa_filter_home_query' );

    In the sidebar:

    <form name="tags" onChange="document.forms.tags.submit();">
    		<?php
    		if (is_category()){
    		  $cat = get_query_var('cat');
    		  $yourcat = get_category ($cat);
    		}
    		$tag_IDs = array();
    		query_posts('category_name='.$yourcat->slug);
    		if (have_posts()) : while (have_posts()) : the_post();
    		  $posttags = get_the_tags();
    		  if ($posttags):
    			foreach($posttags as $tag) {
    			if (!in_array($tag->term_id , $tag_IDs)):
    			   $tag_IDs[] = $tag->term_id;
    			   $tag_names[$tag->term_id] = $tag->name;
    			   $tag_slug[$tag->term_id] = $tag->slug;
    			 endif;
    			}
    		  endif;
    		endwhile; endif;
    		wp_reset_query();
    
    		if (!empty($tag_IDs)){
    			echo '<h3>Het meest geschikt voor</h3>';
    			echo "<input type=\"radio\" name=\"tag\" value=\"\"> Alles weergeven<br>";
    		}
    		foreach($tag_IDs as $tag_ID){
    			$checked = $tag_slug[$tag_ID];
    			echo '<input type="radio" name="tag" value="'.$checked.'"' ;
    			if((isset($_GET["tag"])) && $_GET["tag"] == $checked) {
    			echo ' checked="checked"';
    			}
    			echo '> '.$tag_names[$tag_ID].'<br>';
    		}
    		?>
    
    		<div class="margin25px"></div>
    
    		<h3>Land</h3>
    			<input type="radio" name="land" value=""> Alles weergeven<br>
    			<input type="radio" name="land" value="nederland" <?php if((isset($_GET["land"])) && $_GET["land"] == "nederland") { echo "checked";}?>> Nederland<br>
    			<input type="radio" name="land" value="belgie" <?php if((isset($_GET["land"])) && $_GET["land"] == "belgie") { echo "checked";}?>> Belgie
    
    		<div class="margin25px"></div>
    
    		<h3>Regio</h3>
    			<input type="radio" name="provincie" value=""> Alles weergeven<br>
    			<input type="radio" name="provincie" value="gelderland" <?php if((isset($_GET["provincie"])) && $_GET["provincie"] == "gelderland") { echo "checked";}?>> Gelderland<br>
    			<input type="radio" name="provincie" value="overijssel" <?php if((isset($_GET["provincie"])) && $_GET["provincie"] == "overijssel") { echo "checked";}?>> Overijssel
    		</form>

    The url on page one looks like this for example (which is working):
    /cat/activiteit/?tag=test-tag&land=nederland&provincie=overijssel

    The url on page two looks like this for example (which gives a 404 error):
    /cat/activiteit/page/2/?tag=test

    I'm very happy you take the time to help/teach me! I'm learning a lot here.

  13. bcworkz
    Member
    Posted 1 year ago #

    I'm pleased you are happy, it makes me happy as well :)

    I have some what lost context of your setup over time, it is good you brought me up to date with the latest code. It is clear now that the 404 is related to the main query, so WP should be handling pagination for you, there should be no need for the work around suggested in the link I provided. I'm sorry I set you upon the wrong path with that.

    One problem I see is that the URL parameters for page 1 and page 2 do not match. Without the URL parameters, your 'pre_get_posts' callback cannot set the proper query vars. So even if there was not a 404, the page 2 shown would be for the wrong query anyway. The pagination URLs need to contain the same URL parameters as for the first page. This may cure the 404 issue, or not. Even if not, this still must be corrected or you will be getting the wrong content once the 404 issue is fixed.

    Is your template displaying the results using next_posts_link() for pagination? It is supposed to pickup URL parameters from the current request, but even if it fails, you can use the 'get_pagenum_link' filter to correct the problem. You can get the missing parameters from the query vars you set or from $_SERVER['REQUEST_URI'].

  14. edow
    Member
    Posted 1 year ago #

    Indeed I use the previous_posts_link and the next_posts_link links.
    I think I wasn't clear about it, but these buttons do take the URL parameters to the next page (my example was wrong).

    I've tested it a little bit more and now I it does this (there are 9 posts per page):

    1. With more then 9 posts I use the next_posts_link link and it takes the URL parameter to the next page and that's working good.
    2. When I'm on page 2 and I click on the "land" with value "Nederland" it filters, because there are 10 "lands" with the value "Nederland", but it shows on page 2 the 10th post (and it shows the previous_posts_link), so I think that's why on page 2 with 9 posts or less with a certain value it gives the 404 error.
    3. When I click on a value with for example 2 posts attachted to it (when I'm on page 2) I get the 404 error.

    So, when I'm on the page /cat/activiteit/page/2/ and I start to filter and there are enough posts it's working, but it shows the last posts and you need to click on the previous link to see the rest. And if there are for example 2 posts it gives the 404 error.

  15. bcworkz
    Member
    Posted 1 year ago #

    Ah, I see. In a sense, WP is delivering exactly what you ask for, the second page of further filtered results, of which there are none, so WP reports nothing was found, albeit rather rudely. Probably the easiest way to handle this is to always reset the results page to page 1 any time a filter is added.

    The problem is how is WP to know the difference between a new filter request and a next or previous page request? I've a couple ideas. One is to add an action attribute to the form tag and fill it with the current request without the URL parameters nor any page element in the permalink. You can get the current request from $_SERVER['REQUEST_URI'].

    The other is to add a hidden field to act as a flag signifying that an additional filter was added. In 'pre_get_posts' callback, if this flag/field is found, then set 'paged' to 1. The trick here is to remove the URL parameter so that it is not picked up by next or previous links. You should be able to do this by stripping the URL parameter out of the value stored in $_SERVER['REQUEST_URI'].

    Another approach which could be a nice feature if there are several pages of results is to have code try to guess the equivalent page in the filtered results comparable to the current page so that the results on the current page that remain after filtering will still be on the first page shown page after filtering. I'm not quite sure how to do this, perhaps a prorated page number based on the result count of the current page against the filtered count.

    For example, the current page is page 3 of 6 containing 50 results. The filtered result count will be 34 or 4 pages of results, so the first page shown with the filtered results would be page 2 because 2/4 == 3/6.

    I'm not sure that will always work. I suppose the real solution is to identify which of the results on the current page will remain after filtering and determine which filtered page contains the majority of these results.

  16. edow
    Member
    Posted 1 year ago #

    I'll try what you suggested. In the meanwhile I found at that if the permalink settings are default, like /?cat=1 and I'm on page 2 (/?cat=1&paged=2) and I click on a tag the page goes to the page /?tag=example-tag. But when the permalink settings are /%postname%/ then the 404 error occurs.

    The 404 error redirects to the 404 page. When I put the form code in the normal sidebar (sidebar.php) and I remove the tag which causes the error the page redirects back to the results on page 2 (because in the url the link is still /cat/activiteit/page/2/?land=nederland (for example.)

    To let this setup work correctly I need to know how to remove the ?land= and ?provincie= string from the parameter, because then it's working I think.

    So, the 404 error occurs because of there are not enough search results for page 2.

    I'll try what you suggested and come back here when I found out more.

  17. edow
    Member
    Posted 1 year ago #

    As you suggested I tried the hidden field option.

    <input type="hidden" name="paged" value="1">

    This works for me.

    Before that I made a special sidebar function for the 404.php page, but that isn't necessary anymore it seems. It was this code:

    $tag = $_GET["tag"];
    $land = $_GET["land"];
    $provincie = $_GET["provincie"];
    
    if (!empty($tag)) {
    	$showSidebar = 'category';
    	}
    elseif (!empty($land)) {
    	$showSidebar = 'category';
    	}
    elseif (!empty($provincie)) {
    	$showSidebar = 'category';
    	}
    else{
    	$showSidebar = '';
    	}
    
    get_sidebar($showSidebar);

    So, that problem is now solved.

    The last problem with this form is that when I want to show for example all the countries ("land") I need the string ?land= to disappear from the url.

    I thought it to do like this:

    <input type="radio" name="land" value=""> Show all<br>

    but that doesn't work. With the tag it already does automatically, but it isn't working for other keys. The url becomes /?land and the checkbox isn't checked. So, or the string needs te be removed from the url (so it doesn't filter and thus shows all the countries) or the string needs to be /?land=all and then the query needs to show all the countries.

    How can I handle this?

  18. bcworkz
    Member
    Posted 1 year ago #

    Awesome! I'm glad the hidden field solved the pagination issue.

    In order to show all land entries, removing the land from the URL would probably need to be done with javascript, if it is even possible. I'm not that familiar with the internals of making an URL from form elements, so I'm inclined to let that part be and sort it out with PHP when it arrives at the server.

    Depending on how the form is setup, the value of $_GET['land'] would be an empty string (correct?), which is quite different to PHP than it not being set at all. You would need to alter the if/else structure of the 'pre_get_posts' callback. There are two portions which involve land. The one where land is the only thing set is easy, just add another conditional to the is_main_query && isset part: && $_GET['land'] != "" so the setting of 'meta_query is suppressed.

    The combination land provencie is a bit more complicated, but the same in concept. In this case you could add a separate if clause just before the 'meta_query' is set that unsets the land portion of the array if $_GET['land'] == ""). Exactly how to reference that portion can be tricky, var_dumping the array helps get the reference right. I think it is unset( $meta_query[0]) but var_dump the result to be sure.

  19. edow
    Member
    Posted 1 year ago #

    Thanks for your reply. Instead of an empty string I changed the value to ?land=all.

    I used your suggested code in functions.php, but a little different:

    function wpa_filter_home_query( $query ){
    	if( $query->is_main_query()
        && isset( $_GET['land'] )
    	&& isset( $_GET['provincie'] )
    	&& $_GET['land'] != "all"
    	&& $_GET['provincie'] != "all" ) {
    		$meta_query = array(
    		'relation' => 'AND',
    			array(
                    'key' => 'land',
                    'value' => array( $_GET['land'] )
                ),
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    	elseif( $query->is_main_query()
    	&& isset( $_GET['land'] )
    	&& $_GET['land'] != "all" ) {
            $meta_query = array(
    			array(
                    'key' => 'land',
                    'value' => array( $_GET['land'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    	elseif( $query->is_main_query()
    	&& isset( $_GET['provincie'] )
    	&& $_GET['provincie'] != "all" ) {
            $meta_query = array(
    			array(
                    'key' => 'provincie',
                    'value' => array( $_GET['provincie'] )
                )
            );
            $query->set( 'meta_query', $meta_query );
        }
    }
    add_action( 'pre_get_posts', 'wpa_filter_home_query' );

    Is && $_GET['land'] != "all" used alright? Or should I use another IF statement? It seems to work right now, but I want a clean code.

    In my sidebar I used the following code:

    $land = $_GET["land"];
    $provincie = $_GET["provincie"];
    if ($land == 'all') {
    $showall_land = 'checked';
    }
    
    <h3>Land</h3>
    <input type="radio" name="land" value="all" <?php echo $showall_land; ?>> Alles weergeven<br>}

    And if clicked "Alles weergeven" the url is /?land=all.

    It seems to work properly, but I need to test it a little bit more. Because the string isn't empty I guess I don't need to unset the query anymore?

    Thanks again!! And hopefully you can confirm my code above is properly and so the form is finished :)

  20. bcworkz
    Member
    Posted 1 year ago #

    Yes, setting it to "all" is fine, it only matters that that state is discernible from the other states. Anything to achieve that is fine.

    I agree, the unset is not required the way you are approaching the problem, at least I think so. When both fields are "all", none of the conditions apply and no filtering is applied, which is exactly what you want. Still, there are a lot of possible variations, so thorough testing to ensure we are not overlooking something is very smart.

    AFAICT, your code appears fine, I don't see any problems. I do believe you've finally got it! Nice work :)

  21. edow
    Member
    Posted 1 year ago #

    Thanks for your reply. I'll test it some more soon. Thanks again for all your great help!! You solved the biggest problems on my website. I'm very happy and again I learned a lot.

  22. edow
    Member
    Posted 1 year ago #

    I'm extending the form and came with the following idea to show only the "regio" which belongs to the right "land":

    <form name="sidebarform" onChange="document.forms.sidebarform.submit();">
    		<input type="hidden" name="paged" value="1">
    
    		<?php
    		if (is_category()){
    		  $cat = get_query_var('cat');
    		  $yourcat = get_category ($cat);
    		}
    		$tag_IDs = array();
    		query_posts('category_name='.$yourcat->slug);
    		if (have_posts()) : while (have_posts()) : the_post();
    		  $posttags = get_the_tags();
    		  if ($posttags):
    			foreach($posttags as $tag) {
    			if (!in_array($tag->term_id , $tag_IDs)):
    			   $tag_IDs[] = $tag->term_id;
    			   $tag_names[$tag->term_id] = $tag->name;
    			   $tag_slug[$tag->term_id] = $tag->slug;
    			 endif;
    			}
    		  endif;
    		endwhile; endif;
    		wp_reset_query();
    
    		$getTag = $_GET["tag"];
    		if ($getTag == '') {
    			$tag_showall = 'checked';
    			}
    		if (!empty($tag_IDs)){
    			echo '<h3>Het meest geschikt voor</h3>';
    			echo '<input type="radio" name="tag" value="" '.$tag_showall.'> Alles weergeven<br>';
    		}
    		foreach($tag_IDs as $tag_ID){
    			$checked = $tag_slug[$tag_ID];
    			echo '<input type="radio" name="tag" value="'.$checked.'"' ;
    			if((isset($_GET["tag"])) && $_GET["tag"] == $checked) {
    			echo ' checked="checked"';
    			}
    			echo '> '.$tag_names[$tag_ID].'<br>';
    		}
    		?>
    
    		<div class="margin25px"></div>
    
    		<?php
    			$land = $_GET["land"];
    			$regio = $_GET["regio"];
    
    			if ($land == 'all' OR $land == '') {
    			$land_showall = 'checked';
    			}
    			elseif ( $land == 'nederland' ) {
    			$landNL = 'checked';
    			}
    			elseif ( $land == 'belgie' ) {
    			$landBE = 'checked';
    			}
    			if ($regio == 'all' OR $regio == '') {
    			$regio_showall = 'checked';
    			}
    			elseif ( $regio == 'groningen' ) {
    			$regioNL1 = 'checked';
    			}
    			elseif ( $regio == 'friesland' ) {
    			$regioNL2 = 'checked';
    			}
    			elseif ( $regio == 'drenthe' ) {
    			$regioNL3 = 'checked';
    			}
    			elseif ( $regio == 'overijssel' ) {
    			$regioNL4 = 'checked';
    			}
    			elseif ( $regio == 'flevoland' ) {
    			$regioNL5 = 'checked';
    			}
    			elseif ( $regio == 'gelderland' ) {
    			$regioNL6 = 'checked';
    			}
    			elseif ( $regio == 'utrecht' ) {
    			$regioNL7 = 'checked';
    			}
    			elseif ( $regio == 'noord-holland' ) {
    			$regioNL8 = 'checked';
    			}
    			elseif ( $regio == 'zuid-holland' ) {
    			$regioNL9 = 'checked';
    			}
    			elseif ( $regio == 'zeeland' ) {
    			$regioNL10 = 'checked';
    			}
    			elseif ( $regio == 'noord-brabant' ) {
    			$regioNL11 = 'checked';
    			}
    			elseif ( $regio == 'limburg' ) {
    			$regioNL12 = 'checked';
    			}
    			elseif ( $regio == 'namen' ) {
    			$regioBE1 = 'checked';
    			}
    			elseif ( $regio == 'waals-brabant' ) {
    			$regioBE2 = 'checked';
    			}
    			elseif ( $regio == 'west-vlaanderen' ) {
    			$regioBE3 = 'checked';
    			}
    		?>
    
    		<h3>Land</h3>
    			<input type="radio" name="land" value="all" <?php echo $land_showall; ?>> Alles weergeven<br>
    			<input type="radio" name="land" value="nederland" <?php echo $landNL; ?>> Nederland<br>
    			<input type="radio" name="land" value="belgie" <?php echo $landBE; ?>> Belgiƫ
    
    			<?php
    		if ( $land == 'all' OR $land == '' ) {
    		echo '<div class="margin25px"></div>';
    		echo '<h3>Regio</h3>';
    		echo '<input type="radio" name="regio" value="all" '.$land_showall.'> Alles weergeven<br>';
    		echo '<input type="radio" name="regio" value="groningen" '.$regioNL1.'> Groningen<br>';
    		echo '<input type="radio" name="regio" value="friesland" '.$regioNL2.'> Friesland<br>';
    		echo '<input type="radio" name="regio" value="drenthe" '.$regioNL3.'> Drenthe<br>';
    		echo '<input type="radio" name="regio" value="overijssel" '.$regioNL4.'> Overijssel<br>';
    		echo '<input type="radio" name="regio" value="flevoland" '.$regioNL5.'> Flevoland<br>';
    		echo '<input type="radio" name="regio" value="gelderland" '.$regioNL6.'> Gelderland<br>';
    		echo '<input type="radio" name="regio" value="utrecht" '.$regioNL7.'> Utrecht<br>';
    		echo '<input type="radio" name="regio" value="noord-holland" '.$regioNL8.'> Noord-Holland<br>';
    		echo '<input type="radio" name="regio" value="zuid-holland" '.$regioNL9.'> Zuid-Holland<br>';
    		echo '<input type="radio" name="regio" value="zeeland" '.$regioNL10.'> Zeeland<br>';
    		echo '<input type="radio" name="regio" value="noord-brabant" '.$regioNL11.'> Noord-Brabant<br>';
    		echo '<input type="radio" name="regio" value="limburg" '.$regioNL12.'> Limburg<br><br>';
    		echo '<input type="radio" name="regio" value="namen" '.$regioBE1.'> Namen<br>';
    		echo '<input type="radio" name="regio" value="waals-brabant" '.$regioBE2.'> Waals-Brabant<br>';
    		echo '<input type="radio" name="regio" value="west-vlaanderen" '.$regioBE3.'> West-Vlaanderen<br>';
    		}
    
    		elseif ( $land == 'nederland' ) {
    		echo '<div class="margin25px"></div>';
    		echo '<h3>Regio</h3>';
    		echo '<input type="radio" name="regio" value="all" '.$regio_showall.'> Alles weergeven<br>';
    		echo '<input type="radio" name="regio" value="groningen" '.$regioNL1.'> Groningen<br>';
    		echo '<input type="radio" name="regio" value="friesland" '.$regioNL2.'> Friesland<br>';
    		echo '<input type="radio" name="regio" value="drenthe" '.$regioNL3.'> Drenthe<br>';
    		echo '<input type="radio" name="regio" value="overijssel" '.$regioNL4.'> Overijssel<br>';
    		echo '<input type="radio" name="regio" value="flevoland" '.$regioNL5.'> Flevoland<br>';
    		echo '<input type="radio" name="regio" value="gelderland" '.$regioNL6.'> Gelderland<br>';
    		echo '<input type="radio" name="regio" value="utrecht" '.$regioNL7.'> Utrecht<br>';
    		echo '<input type="radio" name="regio" value="noord-holland" '.$regioNL8.'> Noord-Holland<br>';
    		echo '<input type="radio" name="regio" value="zuid-holland" '.$regioNL9.'> Zuid-Holland<br>';
    		echo '<input type="radio" name="regio" value="zeeland" '.$regioNL10.'> Zeeland<br>';
    		echo '<input type="radio" name="regio" value="noord-brabant" '.$regioNL11.'> Noord-Brabant<br>';
    		echo '<input type="radio" name="regio" value="limburg" '.$regioNL12.'> Limburg';
    		}
    
    		elseif ( $land == 'belgie' ) {
    		echo '<div class="margin25px"></div>';
    		echo '<h3>Regio</h3>';
    		echo '<input type="radio" name="regio" value="all" '.$regio_showall.'> Alles weergeven<br>';
    		echo '<input type="radio" name="regio" value="namen" '.$regioBE1.'> Namen<br>';
    		echo '<input type="radio" name="regio" value="waals-brabant" '.$regioBE2.'> Waals-Brabant<br>';
    		echo '<input type="radio" name="regio" value="west-vlaanderen" '.$regioBE3.'> West-Vlaanderen<br>';
    		}
    		?>
    		</form>

    It's working, but there's one problem. If I click on "belgie" it shows the "regio" which are in "belgie". For example I click on "namen" the URL will be like /?land=belgie&regio=namen. That's alright.
    But when after that I click on "nederland" (so another "land") the URL become /?land=nederland&regio=namen. Which is wrong, because "namen" is not in "nederland".

    Because of this the posts aren't filtering the right way. What I want is when I change the "land" the "regio" will be "all".
    So, every time "land" is clicked the URL should be /?land=belgie&regio=all (if clicked on the land "belgie") OR /?land=nederland&regio=all (if clicked on the land "nederland) OR /?land=all&regio=all (if clicked on the land "all").

    I hope I'm clear in what I want. I tried a lot of things, even with hidden fields, but only the radio buttons change and not the URL.

    Is it possible and if so, what do I do wrong?

  23. bcworkz
    Member
    Posted 1 year ago #

    Hello, sorry for the slow reply, I've been traveling.

    I'm pretty sure I understand what you are trying to achieve. At an abstract level, any time a particular level changes, all lower levels need to be reset to "all" since what ever was selected is no longer applicable. I'm not sure specifically how you should achieve this, I'm inclined to say this should be a javascript solution since PHP cannot know what variations of radio selections the user may go through before finally submitting the form.

    In any case, you say the radio buttons are working correctly, only the resulting URL is wrong. Is the URL wrong for pages other than One, or wrong for page One as well? If other than page One, then the logic for setting the hidden field needs to be reviewed.

    I fear the problem is for page One, which is quite perplexing. The URL should be reflecting the state of the radio buttons, it is part of what browsers do, we do not typically concern ourselves with this, it just works. If it does not work, I'm not sure what to suggest, it is beyond my experience.

    To be sure we are speaking of the same URL, I understand the URL you are seeing as wrong is the URL that is generated when the form is submitted. For example, the radios Belgie and Namen are currently selected. You change the Land to Nederland. The Regio button that was Namen changes to All, but the URL generated is /?land=nederland&regio=namen, is this correct? If not, what am I missing?

  24. edow
    Member
    Posted 1 year ago #

    Hi, no problem at all. I hope you had a great time.

    When Belgie and Namen are currently selected and I change Land to Nederland then the regio button is not selected at all. The URL is indeed /?land=nederland&regio=namen which is wrong for what I want, but I think logical for PHP.

    If I'm on page 2 and I submit the form it redirects to page one, so I'm not sure if it's working on other pages, but I don't think it's a PHP problem, but I think I want something which is not possible with PHP :)

    As you say I think with javascript should be checked if there's a change in the radio button Land and then reset the Regio button. I asked for a javascript solution on Stackoverflow, but with no results. Maybe I have to ask it once more.

    Again thank you for your insight, I'll see if I can make it happen with javascript.

  25. edow
    Member
    Posted 1 year ago #

    Someone made a Javascript solution for me. Everything works fine now.

  26. bcworkz
    Member
    Posted 1 year ago #

    That's great news! Thanks for reporting back, I'm wishing all the best for you and your site :)

  27. edow
    Member
    Posted 1 year ago #

    Thanks a lot! To thank you for all your help I can mention your name and website on the new website if you like. I'm on holiday tomorrow, so if you would like that I hear it when I'm back.

  28. bcworkz
    Member
    Posted 1 year ago #

    While a mention is not in any way necessary, I would be quite honored to be mentioned. I appreciate the thought, I'm just pleased I was able to help. Even though you are reading this on your return, right now I am wishing you an enjoyable holiday.

  29. edow
    Member
    Posted 1 year ago #

    Thanks, I had a great time. I'd be very happy to mention your name on the website. In about a month the new website will be online, so right now you only see the "old" website. If you want you can email me at info@aigoo.nl and let me know how you want to be mentioned. Do not feel obligated.

Topic Closed

This topic has been closed to new replies.

About this Topic