Using ISSET with checkboxes

牧云@^-^@ 提交于 2019-12-07 10:25:14

问题


I am working on a wordpress search form to refine the current search and what Im trying to do is have the search results page with the search from and it's values set based on the query.

So far I've been successful in doing so with single select drop downs and single checkboxes like so --

<!-- SINGLE SELECT -->
    <select name="baths" class="form-control">
    <?php if (isset($_GET['baths'])) {
        $bths = $_GET['baths']; ?>
    <option value="<?php echo $bths; ?>"><?php echo $bths; ?></option>  
    <?php } else { ?>
    <option value="Any">Any</option>
    <?php } ?>
    <option value="Any">Any</option>
    <option value="1">1+</option>
    <option value="2">2+</option>
    <option value="3">3+</option>
    <option value="4">4+</option>
    <option value="5">5+</option>
    <option value="6">6+</option>
    <option value="7">7+</option>
    <option value="8">8+</option>
    <option value="9">9+</option>
    <option value="10">10+</option>
    </select>

<!-- SINGLE CHECKBOX -->
<input type="checkbox" name="dogs" class="styled" value ="yes" <?php if (isset($_GET['dogs'])) { ?>checked<?php } ?>>

That works, but for the multiple values it doesn't. This is my function to generate a set of checkboxes to select amenities -

<?php
$amenity_array = array();
$id            = get_query_var('site');
if (!empty($id)) {
  $property_amenities = get_post_meta($id, 'imic_property_amenities', true);
  global $imic_options;
  foreach ($property_amenities as $properties_amenities_temp) {
    if ($properties_amenities_temp != 'Not Selected') {
      array_push($amenity_array, $properties_amenities_temp);
    }
  }
}
global $imic_options;
if (isset($imic_options['properties_amenities']) && count($imic_options['properties_amenities']) > 1) {
  foreach ($imic_options['properties_amenities'] as $properties_amenities) {
    $am_name = strtolower(str_replace(' ', '', $properties_amenities));
    $check   = '';
    if (in_array($properties_amenities, $amenity_array)) {
      $check = 'checked="checked"';
    }

<!-- HERE I TRY TO FIND THE SELECTED CHECKBOXES AND CHECK THEM OFF -->
    if (isset($_GET['p_am'])) {
      $ams = $_GET['p_am'];

      echo '<div class="checkbox"><input type="checkbox" name="p_am" ' . $check . ' class="styled" value ="' . $properties_amenities . '"><label for="' . $am_name . '">' . $properties_amenities . '</label></div>';
    } else {
      echo '<div class="checkbox"><input type="checkbox" name="p_am" ' . $check . ' class="styled" value ="' . $properties_amenities . '"><label for="' . $am_name . '">' . $properties_amenities . '</label></div>';
    }
<!-- END ISSET -->

  }
} else {
  _e('There is no Properties Amenities', 'framework');
}
?>

For the multi select drop down I am using bootstrap multiselect, so on my template the code looks like this --

<select name="property_type[]" id="pt-multi" class="form-control multi-select2" multiple="multiple">
<?php
 $terms = get_terms( "property-type", array( 'hide_empty' => 0 ) );
 $count = count($terms);
 if ( $count > 0  ){
   echo "<option value='Any'>All</option>";
   foreach ( $terms as $term ) {
     echo "<option value='" . $term->slug . "'>" . $term->name . "</option>";
   }
 }
?>
</select>

On the page it renders out as ---

<select name="property_type[]" id="pt-multi" class="form-control multi-select2 iOSselect" multiple="multiple" style="display: none;">
  <option value="Any">All</option>
  <option value="co-op">Co-Op</option>
  <option value="condo">Condo</option>
</select>

<div class="btn-group" style="width: 100%;">
  <button type="button" class="multiselect dropdown-toggle btn btn-default form-control multi-select2" data-toggle="dropdown" title="Property Type" style="width: 100%; overflow: hidden; text-overflow: ellipsis;">
  <span class="multiselect-selected-text">Property Type</span> 
  <b class="caret"></b></button>
  <ul class="multiselect-container dropdown-menu pull-right">
    <li class="multiselect-item multiselect-all">
      <a tabindex="0" class="multiselect-all">
        <label class="checkbox"><input type="checkbox" value="multiselect-all">  Select all</label>
      </a>
    </li>
    <li>
      <a tabindex="0"><label class="checkbox">
        <input type="checkbox" value="Any"> All</label>
      </a>
    </li>
    <li>
      <a tabindex="0"><label class="checkbox"><input type="checkbox" value="co-op"> Co-Op</label>
      </a>
    </li>
    <li>
      <a tabindex="0"><label class="checkbox"><input type="checkbox" value="condo"> Condo</label>
      </a>
    </li>
  </ul>
</div>

Any ideas?

UPDATE

Using my code from above my amenities checkbox renders out on the page like so ---

<div>
  <label>amenities</label>
  <div class="checkbox">
    <input type="checkbox" name="p_am" class="styled" value="Doorman (Full Time)">
    <label for="doorman(fulltime)">Doorman (Full Time)</label>
  </div>

  <div class="checkbox">
    <input type="checkbox" name="p_am" class="styled" value="Doorman (Part Time)"><label for="doorman(parttime)">Doorman (Part Time)</label>
  </div>

  <div class="checkbox">
    <input type="checkbox" name="p_am" class="styled" value="Laundry (In-Unit)"><label for="laundry(in-unit)">Laundry (In-Unit)</label>
  </div>

  <div class="checkbox">
    <input type="checkbox" name="p_am" class="styled" value="Fitness Center"><label for="fitnesscenter">Fitness Center</label>
  </div>
</div>

This works with my search function allowing users to check off which amenities to include in the query string --

p_am=Doorman+%28Full+Time%29&p_am=Indoor+Pool

My search function is extensive but as far the relevant parts to the amenities -

$amenities = isset($_GET['p_am'])?$_GET['p_am']:'';
$amenities = ($amenities == __('Any', 'framework')) ? '' : $amenities;

// .....

if (!empty($amenities)) {
  array_push($meta_query,array(
    'key' => 'imic_property_amenities',
    'value' => $amenities,
    'compare'=>'LIKE'
  ));
}

UPDATE

In regards to setting the dropdown options for the bootstrap multiselect, I'm trying to set the options using the following code -

<?php 

$taxonomyName = "city-type";

$parent_terms = get_terms( $taxonomyName, array( 'parent' => 0, 'orderby' => 'slug', 'hide_empty' => false ) );

echo "<select name='property_nhb[]' class='form-control multi-select' id='p-nhb' multiple>";

foreach ( $parent_terms as $pterm ) {
 // echo "<option data-val='" . $pterm->slug . "' value='Any' " . $selected . ">Any</option>";
    //Get the Child terms
    $terms = get_terms( $taxonomyName, array( 'parent' => $pterm->term_id, 'orderby' => 'slug', 'hide_empty' => false ) );
    foreach ( $terms as $term ) { 

if(isset($_GET['property_nhb[]'])) {
$pnhb = $_GET['property_nhb'];

$selected = 'selected';

}

        echo "<option data-val='" . $pterm->slug . "' value='" . $term->slug . "' " . $selected . " >" . $term->name . "</option>"; 
    }
}
echo "</select>"; 
?>

My current search function code


回答1:


This seems a little backwards for creating a search form - it seems more like you're generating a form for each individual result? Annotated code and comments below. I've tried to keep to your coding style in my answer.

$amenity_array = array();
$id            = get_query_var('site');
// this first section gets the selected meta properties for the queried property (if available)
// [skipping for brevity ]
global $imic_options;
if (isset($imic_options['properties_amenities']) && count($imic_options['properties_amenities']) > 1) {
  // this loops over all of the globally defined properties
  foreach ($imic_options['properties_amenities'] as $properties_amenities) {
    // gets the name of the property
    $am_name = strtolower(str_replace(' ', '', $properties_amenities));
    // and sets up to check the box if the property has the defined amenity
    // if this is for a search form, why check boxes based on a result?
    $check   = '';
    if (in_array($properties_amenities, $amenity_array)) {
      // note: this only really needs to be 'checked'
      $check = 'checked="checked"';
    }

Here's where things go a little cross-purposes, though.

    if (isset($_GET['p_am'])) {
      $ams = $_GET['p_am'];

      echo '<div class="checkbox"><input type="checkbox" name="p_am" ' . $check . ' class="styled" value ="' . $properties_amenities . '"><label for="' . $am_name . '">' . $properties_amenities . '</label></div>';
    } else {
      echo '<div class="checkbox"><input type="checkbox" name="p_am" ' . $check . ' class="styled" value ="' . $properties_amenities . '"><label for="' . $am_name . '">' . $properties_amenities . '</label></div>';
    }

This says that all checkboxes have the same name ("p_am") instead of using the loop name for the amenity ($am_name) or some form combination if you want all amenities in the same search input array (e.g. "p_am[$am_name]").

Each checkbox would also change the value of $check if supplied to the $_GET array.

      $ams = $_GET['p_am'];
      if (isset($ams[$am_name])) {
        $check = 'checked';
      }

Each checkbox would have name="p_am['.$am_name.']" as the name.

      echo '<div class="checkbox"><input type="checkbox" name="p_am[' . $am_name . ']" ' . $check . ' class="styled" value ="' . $properties_amenities . '"><label for="' . $am_name . '">' . $properties_amenities . '</label></div>';

If you want each of the amenities to have unique names (looking at the original checkbox which isn't called p_am at all) and not be in an array in PHP, then you would just use the loop name for the amenity ($am_name), like so:

      if (isset($_GET[$am_name])) {
        $check = 'checked';
      }

Each checkbox would have name="'.$am_name.'" as the name.

UPDATE: after the OP was updated, it looks like every checkbox needs to have the same name, but not be keyed values. For this situation, your checkboxes should be called p_am[] (on both search page an original page), and you need to use something like in_array() instead of isset() to check the result, like so:

      if (in_array($properties_amenities, $_GET['p_am'])) {
        $check = 'checked';
      }

Additional note - you're also using $am_name for the label, without actually setting the id attribute on the checkbox to match to, as well as not stripping out non-id characters (like parentheses), so the label association won't work.

      echo '<div class="checkbox"><input type="checkbox" name="' . $am_name . '" ' . $check . ' class="styled" value ="' . $properties_amenities . '"><label for="' . $am_name . '">' . $properties_amenities . '</label></div>';

For the bootstrap select, you're just missing a check for which options are selected:

<select name="property_type[]" id="pt-multi" class="form-control multi-select2" multiple="multiple">
<?php
$terms = get_terms( "property-type", array( 'hide_empty' => 0 ) );
$count = count($terms);
if ( $count > 0  ){
  echo "<option value='Any'>All</option>";
  foreach ( $terms as $term ) {
    // if the option is 'checked', you need to add the 'selected' atttibute here
    echo "<option value='" . $term->slug . "'>" . $term->name . "</option>";
  }
}
?>
</select>

So the inside of the loop would look something like this instead:

    // for efficiency's sake should live outside the loop as a one-off, but here for illustrative purposes
    $types = $_GET['property_type'];
    $selected = isset($types[$term->slug]) ? 'selected' : '';
    echo "<option value='" . $term->slug . "'" . $selected . ">" . $term->name . "</option>";

If you're using an older version of bootstrap select, you may need to have the selected string be 'selected="selected" or data-selected="true", depending on the version you're using. For a current version, the above string should be fine.

If the <select> isn't meant to be an array of options either (i.e. not multiple), then the [] should be removed from the name, and would operate similarly to the checkbox code:

<select name="property_type" id="pt-multi" class="form-control multi-select2">
<?php
$terms = get_terms( "property-type", array( 'hide_empty' => 0 ) );
$count = count($terms);
if ( $count > 0  ){
  echo "<option value='Any'>All</option>";
  foreach ( $terms as $term ) {
    $type = $_GET['property_type'];
    $selected = isset($type) && $type == $term-slug ? 'selected' : '';
    echo "<option value='" . $term->slug . "'" . $selected . ">" . $term->name . "</option>";
  }
}
?>
</select>

The original HTML for the <select> doesn't actually 'work' as such either - all it's doing is adding a duplicate <option> to the top of the options list, and because nothing is selected, the form will treat the duplicate created at the top as 'selected' for the <select>.

UPDATE 2: the reason that the search function is breaking with an array of checkbox inputs is because you are using the LIKE comparison for your meta query. From the documentation on WordPress Meta Query:

It can be an array only when compare is 'IN', 'NOT IN', 'BETWEEN', or 'NOT BETWEEN'.

The documentation also shows examples of how to join these together. Since you haven't supplied how you're actually making the search query this is guessing a little, but it looks like for an array of checkboxes your code should be something similar to:

if (!empty($amenities)) {
  foreach ($amenities as $amenity) {
    array_push($meta_query, array(
      'key' => 'imic_property_amenities',
      'value' => $amenity,
      'compare' => 'LIKE'
    ));
  }
}

As with the examples in the documentation, you'll need to make sure there's a relation => 'OR' or relation => 'AND' to define how you want your search to operate.




回答2:


what Fred's meant in the comment is something like this:

<input type="checkbox" value="condo" name="var_name[]">

the [] at the end of the name attribute is to tell PHP that it should treat the variable as an array.

and then in the PHP script, you can just check for the array length using somthing like:

$arr = $_POST['var_name']; echo count($arr);

based on leith's comment, if it is auto generated, then you should not be bothered to check the checkboxes manually.

instead, just make the selected options be selected, for example:

<?php
$selections = $_GET['property_type'];   // or something similar
?>
<select name="property_type[]" id="pt-multi" class="form-control multi-select2" multiple="multiple">
<?php
$terms = get_terms( "property-type", array( 'hide_empty' => 0 ) );
$count = count($terms);
if ( $count > 0  ){
    echo "<option value='Any'>All</option>";
    foreach ( $terms as $term ) {
        $selected = in_array($term->slug, $selections);
        echo "<option value='" . $term->slug . "' " . ($selected?' selected':'') . ">" . $term->name . "</option>";
    }
}
?>
</select>

see this fiddle https://jsfiddle.net/u1w158tp/

in it you just selected the options and it will automatically checked the checkboxes




回答3:


Your checkboxes has the same name. Try to add different name or use "p_am[]" to treat them as array.



来源:https://stackoverflow.com/questions/47557998/using-isset-with-checkboxes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!