3
votes

I would like to set up a widget to filter my post by categories. Let's say, I do have two different categories, "Countries" and "length of stay" with sub categories. Here is an example of what I have:

enter image description here

What I want, is to filter posts by multiple categories. So, If the user is checking the country "Laos" and a length of stay of "2-4Days", I would like to retrieve only posts where the category "Laos" AND the category "2-4Days" has been attached.

I tried to use the Query Multiple Taxonomies pluging. However, this plugging is retrieving all posts with the "Laos" category and all posts with the length of stay of "2-4Days".

I know, that I can filter post with this query, but, I need some help to create this widget with the submit button. Also, I would like to customise it to remove parent categories and display them as a title (remove the checkbox of "Countries" and "Length of stay" and add to them a specific class)?

Working query:

<?php // cat 42=Laos      cat 57=2-4Days
    <?php $my_query_1 = new WP_query(array('category__and' => array(42,57))); ?>
    <?php while ($my_query_1->have_posts()) : $my_query_1->the_post(); ?>
    <a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to
    <?php the_title(); ?>"><?php the_title(); ?><?php the_excerpt(); ?></a>
    <?php endwhile; ?>

Thanks for helping

What I have done :

  1. I create a new side-bar where I want to add the new form
  2. I create the template "sidebar-filters.php" of this new side bar. Here is the code That I had inside it.

    <div id="secondary" class="widget-area" role="complementary">
    I'm the sidebar filters
    <?php
    
        $current_countries = get_query_var('countries');
        $current_stays = get_query_var('stays');
    
        $countries = get_categories('child_of=62');
        $stays = get_categories('child_of=63');
    ?>
    
    <form action="<?php the_permalink(); ?>" id="filterForm" method="post">
            <ul>
                   <li>
                        <label><b>Countries</b></label>
                  </li><br/>
                  <?php
                    foreach ($countries as $country) {
    //                  var_dump($country->cat_ID);
    //                  var_dump($country->name);
                        echo sprintf('<li><input type="checkbox" name="countries[]" id="checkbox_%s" value="%s" %s',$country->name , $country->cat_ID, set_checked($current_countries, $country));
                        echo sprintf('/><label for="checkbox_%s">%s</label></li>',$country->name,$country->name );
                    } 
                    ?>          
            </ul><br/><br/>
            <ul>
                   <li>
                           <label><b>Length of stay</b></label>
                  </li><br/>
                  <?php
                    foreach ($stays as $stay) {
    //                  var_dump($stay->cat_ID);
    //                  var_dump($stay->slug);
                        echo sprintf('<li><input type="checkbox" name="stays[]" id="checkbox_%s" value="%s" %s',$stay->slug , $stay->cat_ID, set_checked($current_stays, $stay));
                        echo sprintf('/><label for="checkbox_%s">%s</label></li>',$stay->slug,$stay->name );
                    } 
                    ?>                              
            </ul><br/><br/>    
            <ul>
                   <li>
                           <button type="submit">Send email</button>
                   </li>
            </ul>
            <input type="hidden" name="submitted" id="submitted" value="true" />
    </form> 
    

  3. And here is the code that I had in my function.php

function my_query_vars($vars) { array_push($vars, 'countries', 'stays'); return $vars; } add_filter('query_vars', 'my_query_vars');

function set_checked($arr, $value) { $checked = ''; if (!empty($arr) && in_array($value, $arr)) $checked = 'checked'; return $checked; }

function my_query($query)
{
  // You can use is_archive() or whatever you need here
  if ($query->is_main_query() && is_search()) {

    $cat_and = array();

    foreach (array('countries', 'stays') as $variable) {
      $categories = get_query_var($variable);

      if (!empty($categories)) {
        $cat_and = array_merge($cat_and, $categories);
      }
    }

    if (!empty($cat_and)) $query->set('category__and', $cat_and);
  }
}
add_action('pre_get_posts', 'my_query');

But, I'm retrieving nothing for the moment, what do I am doing wrong?
2

2 Answers

3
votes

Here's the basic idea to do this with a form:

First you would have to register new query vars so you can use GET and have the filters in the url (that you can later rewrite if needed):

add_filter('query_vars', 'my_query_vars');
function my_query_vars($vars)
{
  array_push($vars, 'countries', 'stays');
  return $vars;
}

Then create a form and print the categories using an array name for each group of checkboxes. You need to make sure to restore the checkboxes that were checked after submitting the form, you can do this on the same page.

function set_checked($arr, $value)
{
  $checked = '';
  if (!empty($arr) && in_array($value, $arr)) $checked = 'checked';
  return $checked;
}

$current_countries = get_query_var('countries');
$current_stays = get_query_var('stays');

$countries = get_categories('child_of=id_for_countries');
$stays = get_categories('child_of=id_for_length-of-stay');

// Begin form

foreach ($countries as $country) {
  echo sprintf('<input type="checkbox" name="countries[]" value="%s" %s', $country->cat_ID, set_checked($current_countries, $country));
}

foreach ($stays as $stay) {
  echo sprintf('<input type="checkbox" name="stays[]" value="%s" %s/>', $stay->cat_ID, set_checked($current_stays, $stay));
}

// End form

Finally you need to modify the query to filter according to this variables:

add_action('pre_get_posts', 'my_query');
function my_query($query)
{
  // You can use is_archive() or whatever you need here
  if ($query->is_main_query() && is_search()) {

    $cat_and = array();

    foreach (array('countries', 'stays') as $variable) {
      $categories = get_query_var($variable);

      if (!empty($categories)) {
        $cat_and = array_merge($cat_and, $categories);
      }
    }

    if (!empty($cat_and)) $query->set('category__and', $cat_and);
  }
}

I haven't tested it but this should work, hope this helps.

1
votes
   <?php
   $checkboxArray = $_POST['checkbox']; //checkbox[] is name of all your checkboxes
   $catIds = implode(',',$checkboxArray);
  $my_query = new WP_Query('showposts=10&cat='.$catIds); ?>

    <?php while ($my_query->have_posts()) : $my_query->the_post(); ?>

    <a href="<?php the_permalink() ?>" title="<?php the_title(); ?>">

    <?php the_title(); ?></a>

    <?php the_content(); ?> //optional, can also be the_excerpt

    <?php endwhile; ?>

You can change the value of showposts as you required.