Question

Well, I have a Database made mostly with 'Advanced Custom Fields' in a page on my site that is supposed to get all the STORES (custom post type) of a city and show them to me, and by changing dynamically the URL I could made it get a genre, type, etc "www.urltoshow.com/ville/Paris?genre=Man"...

The way I worked this before it was by using this simple piece of code

$genre = $_GET['genre'];
if(empty($genre))$genre = array('Woman','Man'); //For getting all of them when opening the page
                               
if(have_posts() ):
$args = array( 'post_type' => 'store', 
              'meta_key' => 'store_client_type' ,
             'meta_query' => array(
                                 array(
                                'relation' => 'AND',
                                'genre_clause' => array(
                                    'key' => 'store_genre', 
                                    'value' => $genre,
                                    ), 
                                )
                            ),  
             );
$loop = new WP_Query( $args );

AND to filter them for the clients I would use a form like this:

<form class="sample-form"
method="GET"
action="#"
target="_top">
      <select name="genre"
       id="genre">
        <option value="" disabled selected>Genre</option>
        <option value="woman">Woman</option>
        <option value="man">Man</option>
      </select>
      <input type="submit"
             value="GO"
             class=" button-rules">
</form>

AND it usually works wonderfully... BUT when it comes to CHECKBOXES, when I want to select an style(which some stores will have multiple like Vintage and Classic, or Deluxe and Vintage or maybe just Deluxe), and I need it showing one or several values and I need to do it using checkboxes, a simple example would be

<input type="checkbox" id="test1" name="style"
value="Streetwear/Sportwear"/><label for="test1">Streetwear/Sportwear</label>
<br>
<input type="checkbox" id="test4" name="style"
value="Casual/Décontracté"/><label for="test4">Casual/Décontracté</label>

BUT the QUERY doesnt work and does not shows anything when adding the results of that... Here is my full code

<!-- THE FORM -->

    
<form class="sample-form"
method="GET"
action="#"
target="_top">
<select name="genre"
    id="genre">
        <option value="" disabled selected>Genre</option>
        <option value="woman">Woman</option>
        <option value="man">Man</option>
</select>
<select name="type"
    id="type">
        <option value="" disabled selected>type</option>
        <option value="friperie">Second hand</option>
        <option value="ressourcerie">Artisan</option>
</select>
<select name="prix"
id="prix"
class="bars">
<option value="" disabled selected>prix</option>
<option value="€">€</option>
<option value="€€">€€</option>
<option value="€€€">€€€</option>
</select>
<--! AREA TO SOLVE -->
<input type="checkbox" id="test1" name="style"
value="Streetwear/Sportwear"/><label for="test1">Streetwear/Sportwear</label>
<br>
<input type="checkbox" id="test4" name="style"
value="Casual/Décontracté"/><label for="test4">Casual/Décontracté</label>
<br>
<input type="checkbox" id="test5" name="style"
value="Luxe"/><label for="test5">Luxe</label>
<br>
<input type="checkbox" id="test6" name="style"
value="Classique"/><label for="test6">Classique</label>
<br>
<input type="submit"
value="GO"
class=" button-rules">
<div submit-success>
Success!
</div>
<div submit-error>
Error!
</div>
<!-- THE QUERY AND POST -->

 <?php 
 $prix = $_GET['prix'];
 $genre = $_GET['genre'];
 $type = $_GET['type'];
 $style = $_GET['style'];
  if(empty($prix))$prix = array('€€€','€€','€');
  if(empty($genre))$genre = array('Woman','Man');
  if(empty($type))$type = array('friperie','ressourcerie','dépôt-vente');
  if(empty($style))$style = array('Casual/Décontracté','Classique','Luxe','Vintage','Street/Sports','Gothic/Underground' );  ?>
        

<div class="row">         
                            if(have_posts() ):
$args = array( 'post_type' => 'store', 
              'meta_key' => 'store_client_type' ,
             'meta_query' => array(
                                 array(
                                'relation' => 'AND',
                                'price_clause' => array(
                                    'key' => 'store_prix', 
                                    'value' => $prix,
                                    ),
                                'genre_clause' => array(
                                    'key' => 'store_genre', 
                                    'value' => $genre,
                                    ),
                                'type_clause' => array(
                                    'key' => 'store_type', 
                                    'value' => $type,
                                    ),
                                'style_clause' => array(
                                    'key' => 'store_style', 
                                    'value' => $style,
                                    ),  
                                )
                            ),
              'orderby' => array(
                            'city_clause'  => 'desc',
                            'price_clause'  => 'desc',
                            'genre_clause'  => 'desc',
                            'type_clause'  => 'desc',
                            'style_clause'  => 'desc', 
                        )       
             );
$loop = new WP_Query( $args );
    while($loop->have_posts()):  $loop->the_post(); ?>
                <div class="col-12">
                    <h4><?php the_title(); ?></h4>
                  </div>
                            <?php     
    endwhile;  
    endif;
    wp_reset_query(); ?> 

WHEN using this code without the $style it works great and shows me everything, but when adding $style nothing is shown

Was it helpful?

Solution

I am no expert but you are submitting multiple checkboxes with the same name attribute.

Your current form GET action will return the url params like this for example...

http://www.urltoshow.com/ville/paris?style=Classique&syle=Luxe

So because there are 2 usages of param style in the url above, it means PHP $_GET['style'] will only return the last getted param value.

$_GET['style'];
/* only returns Luxe from url above */

Annoying I there is no way to covert multiple url parameter instances into a single value with PHP...




So a work around is use some javascript to handle your form submission field data, and any multiple field name checkbox usages, accumulate these checkbox values to an array, and then convert that array to comma separated value which can be passed into a single style url parameter value.

For example, your form... (form attributes modified)

<form id="sample-form" method="GET" action="/ville/paris">

  <select name="genre">
    <option value="">Select genre...</option>
    <option value="woman">Woman</option>
    <option value="man">Man</option>
  </select>

  <select name="type">
    <option value="">Select type...</option>
    <option value="friperie">Second hand</option>
    <option value="ressourcerie">Artisan</option>
  </select>

  <select name="prix">
    <option value="">Select prix...</option>
    <option value="€">€</option>
    <option value="€€">€€</option>
    <option value="€€€">€€€</option>
  </select>

  <br />

  <input type="checkbox" id="test1" name="style" value="Streetwear/Sportwear" />
  <label for="test1">Streetwear/Sportwear</label>
  
  <br />

  <input type="checkbox" id="test4" name="style" value="Casual/Décontracté" />
  <label for="test4">Casual/Décontracté</label>
  
  <br />

  <input type="checkbox" id="test5" name="style" value="Luxe" />
  <label for="test5">Luxe</label>
  
  <br />

  <input type="checkbox" id="test6" name="style" value="Classique" />
  <label for="test6">Classique</label>

  <br />

  <input type="submit" value="Go" />

</form>

Some jQuery javascript to handle the form submission... (read comments)

// sample form on submit
$('#sample-form').on('submit', function(e) {

  // prevent default
  e.preventDefault();

  // set empty submission object
  let submission = {};

  // for each of this form submit event target object entries as key/field
  for (const [key, field] of Object.entries(e.target)) {

    // if object entry (field) has a name attribute
    if (field.name) {

      // if field type is
      if (field.type === 'checkbox') {

        // if checkbox is checked
        if (field.checked) {
        
          // if submission does not have syle property
          if (!submission.hasOwnProperty('style')) {

            // set field name as array
            submission[field.name] = [];

          }

          // add name/value to submission object
          submission[field.name].push(field.value);

        }

      } else if (field.value) {

        // add name/value to submission object
        submission[field.name] = field.value;

      }

    }

  }

  // now let loop through our submission and check for arrays
  for (const [name, value] of Object.entries(submission)) {

    // if submission value is array
    if (Array.isArray(value)) {

      // let convert array to string
      submission[name] = value.join(',');

    }

  }
  
  // convert submission object to url safe params string
  let submission_url_params = $.param(submission);
  
  // if we have submission params
  if(submission_url_params) {
  
    // success actions
  
    // create our submission action url
        let submission_url_action = this.action + (submission_url_params ? '?' + submission_url_params : '');
    
    // un-comment this to actually fire the form submission
    window.location.href = submission_url_action;

  // else no submission params
  } else {
  
    // no submission data actions
  
  }

});

Here is fiddle of the above form submit script...

So what this script does when the form is submitted is...

  • initially loops through all the form fields that have a name attribute.
  • it also checks if the field type is checkbox. If it is a checkbox with the same name it converts checkbox values into an array.

Example form field selection... (screenshot)

enter image description here

Initial loop in script returns this... (currently style is array)

{
  genre: "woman",
  prix: "€€",
  style: [
    "Casual/Décontracté", 
    "Classique"
  ],
  type: "ressourcerie"
 }

But then at the end of the script it loops any submission value which is_array and coverts to a comma separated string... (style is now a comma separated string)

{
  genre: "woman",
  prix: "€€",
  style: "Casual/Décontracté,Classique",
  type: "ressourcerie"
}

So now our submission has no arrays and all parameters are strings, the script then turns the submission into url params...

?genre=woman&type=ressourcerie&prix=%E2%82%AC%E2%82%AC&style=Casual%2FD%C3%A9contract%C3%A9%2CClassique



Now the PHP part, we can use these url params to build your $query PHP args for your wordpress product loop...

Here is little helpful get_var function to handle $GET usages...

function get_var($name = false, $default = false) {
  if($name === false) {
    return $_REQUEST;
  }
  if(isset($_REQUEST[$name])) {
    return $_REQUEST[$name];
  }
  return $default;
}

Get and set our URL vars using get get_var helper function...

// get and set url params to varibles
$genre  = get_var('genre',['Woman','Man']);
$type   = get_var('type',false);
$prix   = get_var('prix',false);
$style  = get_var('style',false);

Meta Relation Query Option

Now lets build our meta query arguments...

// begin our query args
$args = [
  'post_type'       => 'store',
  'post_status'     => 'publish',
  'posts_per_page'  => 40,
  'orderby'         => 'ASC',
  'meta_query'       => [
    'relation' => 'AND'
  ]
];

// if genre url param
if($genre) {

  // this genre is_array check/loop might not be necessary, you could set the above $genre default as false which should return all genres anyway
  // but i've included your default `['Woman','Man']` arrat meta query for example...
 
  // if genre is array ['woman','man']
  if(is_array($genre)) {

    // convert genre to genres
    $genres = $genre;
    
    // foreach genre
    foreach($genres as $genre) {
       
      // add genre meta query to our args
      $args['meta_query'][] = [
        'genre_clause' => [
          'key'   => 'store_genre', 
          'value' => $genre
        ]
      ];
      
    }
  
  // else genre is singular (not array)
  } else {
  
    // add genre meta query to our args
    $args['meta_query'][] = [
      'genre_clause' => [
        'key'   => 'store_genre', 
        'value' => $genre
      ]
    ];

  }

}

// if type url param
if($type) {
  
  // add type meta query to our args
  $args['meta_query'][] = [
    'type_clause' => [
      'key'   => 'store_type', 
      'value' => $type
    ]
  ];

}

// if prix url param
if($prix) {
  
  // add prix meta query to our args
  $args['meta_query'][] = [
    'type_clause' => [
      'key'   => 'store_prix', 
      'value' => $prix
    ]
  ];

}

// if style url param
if($style) {

  // we need to explode our comma separated styles param into an array
  $styles = explode(',',$style);
  
  // foreach styles param array
  foreach($styles as $style) {
       
    // add style meta query to our args
    $args['meta_query'][] = [
      'style_clause' => [
        'key'   => 'store_style', 
        'value' => $style
      ]
    ];
      
  }

}

Taxonomy Relation Query Option

Now lets build our taxonomy query arguments...

// begin our query args
$args = [
  'post_type'       => 'store',
  'post_status'     => 'publish',
  'posts_per_page'  => 40,
  'orderby'         => 'ASC',
  'tax_query'       => [
    'relation' => 'AND'
  ]
];

// if genre url param
if($genre) {

  // add genre tax query to our args
  $args['tax_query'][] = [
    'taxonomy'  => 'genre', // your genre taxonomy name
    'field'     => 'slug',
    'terms'     => is_array($genre) ? $genre : [ $genre ],
  ];

}

// if type url param
if($type) {
  
  // add type tax query to our args
  $args['tax_query'][] = [
    'taxonomy'  => 'type', // your type taxonomy name
    'field'     => 'slug',
    'terms'     => [ $type ],
  ];

}

// if prix url param
if($prix) {
  
  // add prix tax query to our args
  $args['tax_query'][] = [
    'taxonomy'  => 'prix', // your prix taxonomy name
    'field'     => 'slug',
    'terms'     => [ $prix ],
  ];

}

// if style url param
if($style) {

  // we need to explode our comma separated styles param into an array
  $styles = explode(',',$style);
  
  // add style tax query to our args
  $args['tax_query'][] = [
    'taxonomy'  => 'style', // your style taxonomy name
    'field'     => 'name', // changed to name as your style checkbox values are names (not slugs)
    'terms'     => [ $styles ],
  ];

}

Now using our $args we simply loop...

$loop = new WP_Query($args);
    while($loop->have_posts()):  $loop->the_post();
       the_title();   
    endwhile;  
endif;
Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top