Filters with forms (problem with pluck)

Hi,

I’m following the guide at this page to get a basic store locator working with a couple of select input.

The problem seems to be the $split parameter in the second pluck(). If I remove it everything works fine, but I need to have multiple values available for the $services field.

Any ideas on what may be the problem here? Thanks!

Here is my controller:

return function($site, $pages, $page) {

  $region = $page->children()->pluck('region', null, true);
  $services = $page->children()->pluck('services', ',', true);
  $keys = array('region', 'services');

  $partners = $page->children()->visible();

  if(r::is('POST') && $data = get()) {
    $partners = $page->children()->visible()->filter(function($child) use($keys, $data) {

      foreach($data as $key => $value) {

        if($value && in_array($key, $keys)) {

          if(!$match = $child->$key() == $value) {
            return false;
          }
        }
      }

      return $child;

    });
  }
  return compact('partners', 'region', 'services', 'data');
};

and in my template I have:

<form id="filters" method="post">
  <select name="region" onchange="this.form.submit()">
    <option selected value="">Seleziona la regione</option>
    <?php foreach($region as $item): ?>
    <?php if(!$item) continue ?>
    <option<?php e(isset($data['region']) && $data['region'] == $item, ' selected') ?> value="<?php echo $item->html() ?>"><?php echo $item->html() ?></option>
    <?php endforeach ?>
  </select>
  <select name="services" onchange="this.form.submit()">
    <option selected value="">Seleziona l'area prodotto</option>
    <?php foreach($services as $item): ?>
    <?php if(!$item) continue ?>
    <option<?php e(isset($data['services']) && $data['services'] == $item, ' selected') ?> value="<?php echo $item->html() ?>"><?php echo $item->html() ?></option>
    <?php endforeach ?>
  </select>
</form>

what do you get if you do a var_dump()?

var_dump($services);

array(2) { [0]=> string(9) “service B” [1]=> string(9) “service A” }

Right now I have 3 store listed with the following:

Store 1
services: service A

Store 2
services: service A, service B

Store 3
services: service B

What exactly does not work as expected? Does the form output the options? Do you get any error messages?

The second select don’t get populated and the page stops rendering after that.

I assume there are some problems with the foreach loop in the template but I don’t know what to change to make it work.

Have you turned on debugging in your config.php?

c::set('debug', true);

I can’t see anything obvious, but maybe I’m just blind …:blush:

Debug is on but I don’t get any error…

Since the dump on $services seems ok (it splits Service A and Service B correctly), I tried a var_dump on the $region key and it outputs all the vars stored in Kirby… That seems a bit odd.

Nevermind, if I use the $split parameter in the first pluck() as well the dump is ok:

array(2) { [0]=> string(9) "Lombardia" [1]=> string(5) "Lazio" }

But now the rendering stops at the first select…

<select name="region" onchange="this.form.submit()">
  <option selected="" value="">Seleziona la regione</option>

</select>

Pls. try removing the html() method when echoing the items.

That seem to did the trick for rendering the selects, thanks!

However the filter doesn’t work when there are multiple values in one field (eg. services: service A, service B). It simply doesn’t show the result.

Could you post your filtering code?

The code is the one I took from the Docs. Here it is my controller:

return function($site, $pages, $page) {

  $region = $page->children()->pluck('region', null, true);
  $services = $page->children()->pluck('services', ',', true);
  $keys = array('region', 'services');

  $partners = $page->children()->visible();

  if(r::is('POST') && $data = get()) {
    $partners = $page->children()->visible()->filter(function($child) use($keys, $data) {

      foreach($data as $key => $value) {

        if($value && in_array($key, $keys)) {

          if(!$match = $child->$key() == $value) {
            return false;
          }
        }
      }

      return $child;

    });
  }
  return compact('partners', 'region', 'services', 'data');
};

Oh, sorry, stupid me :blush:

Yeah, you would have to adapt the code a bit, and create an array from the services field and check if the value is in the array.

Maybe that example is not suited for multiple values in fields?
Unfortunately I’m lost after that first if statement and I don’t know how to modify it…

Thank you for helping me!

I don’t have the time now but will look into this later.

Ok, now try this:

return function($site, $pages, $page) {

  $region = $page->children()->pluck('region', null, true);
  $services = $page->children()->pluck('services', ',', true);
  $keys = array('region', 'services');

  $partners = $page->children()->visible();

  if(r::is('POST') && $data = get()) {
    $partners = $page->children()->visible()->filter(function($child) use($keys, $data) {

      foreach($data as $key => $value) {

        if($value && in_array($key, $keys)) {

          if(! $match = in_array($value, $child->$key()->split(','))) {

            return false;
          }
        }
      }

    return $child;

    });
  }
  return compact('partners', 'region', 'services', 'data');
};

The only change is in the line that tests for $match.

1 Like

BTW: I came across the same problem with pluck() and null as split parameter yesterday and created an issue on GitHub as this is a bug.

Now it works, thank you!

Last thing I have to figure out is where to sort alphabetically the two arrays so they selects are tidier.

You can use PHP sort() to sort the resulting arrays:

$region = $page->children()->pluck('region', null, true);
sort($region);
$services = $page->children()->pluck('services', ',', true);
sort($services);

There are several flags you can use with sort(), check out the docs:

http://php.net/manual/de/function.sort.php

1 Like

You’re amazing! Thanks again for all you help.