Filter Pages by multiple fields

Is it possible to filter a list of pages by multiple values using filterBy()?

for example if each page has a field with different values can i then select certain values and filter by these pages?

Something like this:

 ->filterBy('City', 'City-a', 'City-b', ',')

Thanks :slight_smile:

Do you want to filter pages for which all conditions are true or pages where either condition 1 or condition 2 or condition 3 etc. is true?

Anyway, this can’t be done with the filterBy() function, but you could use a custom filter with callback to achieve that, I guess.

Basically I want to have a field called locations and then the value would be one of say 5 different locations. The user will then filter these locations using checkboxes. I have it working with a selectbox and choosing one value but I now need it to filter multiple options at once.

So when the page is reloaded it can show all pages with locationA, locationB or location.

The documentation doesn’t seem too clear for the custom filters though as I did look at that earlier.

here you go (e.g. filtering stores or whatever):

// $selections is an array with the values of the selected checkboxes, don't know how you retrieve them in your setup
// $selections = array('locationA', 'locationB', 'location');
$stores = $pages->filter(function($child) {
  // only $child that return true in here will be part of $stores
  return in_array($child->locations(), $selections);
});
1 Like

would this work for example?

$selections = array('locationA', 'locationB', 'location');
$stores = $pages->filter(function($child) {
  // only $child that return true in here will be part of $stores
  return in_array($child->locations(), $selections);
});

as $selections is an array declared outside the scope of the function

Ah, you probably need to do function($child) use($selections) then.

could you post an example please?

$selections = array('locationA', 'locationB', 'location');
$stores = $pages->filter(function($child) use($selections) {
  // only $child that return true in here will be part of $stores
  return in_array($child->locations(), $selections);
});

Or the following:

$stores = $pages;
foreach(array('locationA', 'locationB', 'locationC') as $location) {
  $stores = $stores->filterBy('location', $location);
}

Hm, that does not seem to work for me :pensive: As an alternative you can add to the collection within the foreach loop:

  $stores = new Pages();
  foreach(array('locationA', 'locationB', 'locationC') as $location) {
     $stores->add($pages->filterBy('location', $location));
  }

Ah, I think I see why. I think this should work:

$stores = clone $pages;
foreach(array('locationA', 'locationB', 'locationC') as $location) {
  $stores = $stores->filterBy('location', $location);
}

@lukasbestle, ok, it does work even without the cloning, but only if you return the results within a nested foreach loop, i.e. your solution does not return a collection you can use in a controller, like the custom filter does.

Hi,
and how does it work if I have really different fields?
Here you filter by the field “location“ if i understand it right. But if I have the fields “zip“ and “location“ as example.
How can I link it together?

Cheers

You can use a filter with a callback like this

$result = $page->children()->filter(function($child) {
  return $child->location() == 'ABC' && $child->zip() == '123';
});

If you want to filter by multiple locations or zips, then use arrays as required:

$locations = ['locationA', 'locationB', 'locationC'];
$zips = ['55122', '55116', '55120', '55129'];
$result = $page->children()->filter(function($child) use($locations, $zips) {
  return in_array($child->location(), $locations)  && in_array($child->zip(), $zips);
});