# How to filter by multiple parameters at the same time?

**URL:** <https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036>\
**Category:** Questions\
**Tags:** v3\
**Created:** [October 22, 2019, 5:53pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036 "2019-10-22T17:53:02Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Roman](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/roman/32/6571_2.png) [@Roman](https://forum.getkirby.com/u/Roman)\
**Post date:** [October 22, 2019, 5:53pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/1 "2019-10-22T17:53:02Z")

</div>

I read some similar discussions but can’t figure out how to do it.

I want to give products 4 or more filters, like: country, producer, type, and make possible to select any combinations, for example, one or two tags from **country** , then some from **producer** etc.

Like in this example: [Monosnap](https://take.ms/Realy)

Solution I am currently using for one group of filters is same as here: [Filtering with tags | Kirby CMS](https://getkirby.com/docs/cookbook/content/filtering-with-tags)

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [October 22, 2019, 6:24pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/2 "2019-10-22T18:24:57Z")

</div>

> [@Multiple filters](https://forum.getkirby.com/t/multiple-filters/15943):
>
> I was playing aroud with Kirby and trying to build some filters content possibilities in the front-end. So I decided to share it here, it can be a starting point for someone. Please consider I’m not a Kirby/php pro dev, even if it works correctly, these codes may have errors or can be better written wink demo [here](https://www.dev.constantinweb.com/kirby-filter-content/)

---

<div class="post-metadata">

**Author:** ![Roman](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/roman/32/6571_2.png) [@Roman](https://forum.getkirby.com/u/Roman)\
**Post date:** [October 22, 2019, 6:30pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/3 "2019-10-22T18:30:53Z")

</div>

Nice solution, didn’t find it, thanks a lot! Will try right now, only noticed that here [https://www.dev.constantinweb.com/kirby-filter-content/related-multiple](https://www.dev.constantinweb.com/kirby-filter-content/related-multiple) after applying filter [https://www.dev.constantinweb.com/kirby-filter-content/related-multiple/type:Album](https://www.dev.constantinweb.com/kirby-filter-content/related-multiple/type:Album), the order of years changes, but that should be easy to change.

---

<div class="post-metadata">

**Author:** ![Roman](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/roman/32/6571_2.png) [@Roman](https://forum.getkirby.com/u/Roman)\
**Post date:** [October 22, 2019, 7:53pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/4 "2019-10-22T19:53:29Z")

</div>

Checked this solution, working fine, only doesn’t select several filters in the same group:

Maybe you can give some hint how to make possible to select both “Single” and “My new” at the same time? 🙂@anon3573533

 ![both](https://europe1.discourse-cdn.com/flex017/uploads/getkirby/original/2X/1/14e276f34d38d9fad947f2a3c3fd37062a06c913.gif)

---

<div class="post-metadata">

**Author:** ![anon3573533](https://avatars.discourse-cdn.com/v4/letter/a/848f3c/32.png) [@anon3573533](https://forum.getkirby.com/u/anon3573533)\
**Post date:** [October 23, 2019, 4:07am UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/5 "2019-10-23T04:07:24Z")

</div>

> [@Roman](#):
>
> Maybe you can give some hint how to make possible to select both “Single” and “My new” at the same time?

hmm this is a good question… I thought to this “option” also, without having tried to make it for the moment because no idea about how to build it. Will add it to github if I find the correct solution. If anyone has any tips… 😉

---

<div class="post-metadata">

**Author:** ![anon3573533](https://avatars.discourse-cdn.com/v4/letter/a/848f3c/32.png) [@anon3573533](https://forum.getkirby.com/u/anon3573533)\
**Post date:** [October 23, 2019, 4:11am UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/6 "2019-10-23T04:11:02Z")

</div>

Yes, I’m sur there are some improvements and corrections to add to these codes, for exemple `urlencode` on links etc…

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [October 23, 2019, 6:54am UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/7 "2019-10-23T06:54:54Z")

</div>

Kirby 3.3.0 has a new [`$collection->when()`](https://github.com/getkirby/getkirby.com/blob/76a4a97fab7316470ce466e9b95d404172c47ad4/content/1_docs/3_reference/4_objects/0_pages/0_when/method.txt) method that makes filtering a lot easier.

Apart from that, if you get an array of options rather than a single value, you can use the available [filter methods](https://getkirby.com/docs/reference/objects/pages/filter-by#available-filter-methods).

@anon3573533’s [multi-filters form example](https://www.dev.constantinweb.com/kirby-filter-content/filters) uses radio fields, for multiple values in one category you need a checkboxes field instead.

---

<div class="post-metadata">

**Author:** ![jonasfeige](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonasfeige/32/4550_2.png) [@jonasfeige](https://forum.getkirby.com/u/jonasfeige)\
**Post date:** [January 12, 2020, 4:46pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/8 "2020-01-12T16:46:23Z")

</div>

Resurrecting this thread because I have run into a similar issue while building a cookbook.

I have several different types of params and can easily filter between those. However, when I want to combine multiple instances of the same param, I am not sure how to properly filter my collection.

Here is my controller:

```
<?php

return function ($site, $page) {

  $recipes = collection('recipes');
  
  /* FILTERS */
  $diets = Str::split(param('diet'), ',');
  $type = param('type');
  $author = param('author');
  $random = param('random');
  $query = get('q'); // Search

  $recipesFiltered = $recipes
    ->when(($diets), function ($diets) {
      return $this->filterBy('diet', 'in', $diets, ', ');
    })
    ->when($type, function ($type) {
      return $this->filterBy('type', $type, ',');
    })
    ->when($author, function ($author) {
      return $this->filterBy('author', "- $author");
    })
    ->when($random, function ($random) {
      return $this->shuffle()->limit($random);
    })
    ->when($query, function ($query) {
      return $this->search($query, 'title|ingredients|diet');
    });

  return [
    'query' => $query,
    'recipes' => $recipes,
    'recipesFiltered' => $recipesFiltered

  ];

};

```

All except for the `$diets` param are single-select, so no problem there. However, I want to be able to combine different types of diet and filter the recipes accordingly. I therefor split the param into an array and then filter the recipes by that array. The problem is that this matches recipes that fit any of the items in the array and not all of them.

So if I have 10 vegan and 15 vegetarian recipes and I filter for “vegan, vegetarian” it should return only 10, not 15 recipes.

As @texnixe suggested in her last comment, I should probably use the `filter` method instead but I haven’t been able to get this working. I tried turning the diet-information of the individual recipe into an array (it’s saved via checkboxes) and I guess I could somehow compare that to my params array?!

I am a bit lost but if someone would be able to point me in the right direction, I’d really appreciate it.

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [January 12, 2020, 4:57pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/9 "2020-01-12T16:57:11Z")

</div>

If you check if something is in an array, `or` logic will be applied, so the result is correct. You would have to use the filter method with a callback using `and` logic.

This should work:

```auto
<?php

->when($diets, function ($diets) {
      return $this->filter(function($child) use($diets) {
          return count(array_diff($diets, $child->diet()->split())) === 0;
      });
  })

```

On a side note, why are you returning two different collections?

The author filter looks a bit strange as well.

---

<div class="post-metadata">

**Author:** ![jonasfeige](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonasfeige/32/4550_2.png) [@jonasfeige](https://forum.getkirby.com/u/jonasfeige)\
**Post date:** [January 12, 2020, 5:34pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/10 "2020-01-12T17:34:51Z")

</div>

Thanks so much, that’s exactly what I was looking for!

Oh, yes, the second recipes collection was a leftover. I have a recipe-counter in the nav and used it for that but I guess I can also just use `'collection('recipes')'` again.

 ![Bildschirmfoto 2020-01-12 um 18.27.06](https://europe1.discourse-cdn.com/flex017/uploads/getkirby/original/2X/2/22e6a9fde382a3cc18b9c8974efabdea4a063736.png)

Regarding the author filter: that’s actually a solution I found here in the forum. It works, but not sure if it’s really the best solution? If I just use `$author` the filter does not work because users are saved with a preceeding `'- '` in the text files.

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [January 12, 2020, 5:57pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/11 "2020-01-12T17:57:34Z")

</div>

> [@jonasfeige](#):
>
> It works, but not sure if it’s really the best solution?

I’d say it’s a bit of a hacky solution. A filter with a callback that turns the field value into a user and then compares the values would be the more correct approach, I think.

```auto
 ->when($author, function ($author) {
     return $this->filter(function($child) use($author) {
        $user = $child->author()->toUser();
        if ($user) {
             return $user->name() === $author; // or whatever you have to compare here
        });
    });
});

```

---

<div class="post-metadata">

**Author:** ![jonasfeige](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonasfeige/32/4550_2.png) [@jonasfeige](https://forum.getkirby.com/u/jonasfeige)\
**Post date:** [January 12, 2020, 6:07pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/12 "2020-01-12T18:07:56Z")

</div>

That does sound more reasonable, will look into it, thanks!

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [January 12, 2020, 6:11pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/13 "2020-01-12T18:11:16Z")

</div>

I posted a possible solution above, not tested.

A lot more complicated then your original solution, though. Wondering if there is no better solution. I’ll check…

The easier, but definitely better than the original version, solution for the author would be:

```auto
  ->when($author, function ($author) {
      return $this->filterBy('author', $author, '-');
    })

```

---

<div class="post-metadata">

**Author:** ![jonasfeige](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/jonasfeige/32/4550_2.png) [@jonasfeige](https://forum.getkirby.com/u/jonasfeige)\
**Post date:** [January 12, 2020, 9:27pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/14 "2020-01-12T21:27:19Z")

</div>

Ah yes, perfect. Thanks a lot!

---

<div class="post-metadata">

**Author:** ![u13712](https://avatars.discourse-cdn.com/v4/letter/u/dfb087/32.png) [@u13712](https://forum.getkirby.com/u/u13712)\
**Post date:** [December 3, 2020, 2:28pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/15 "2020-12-03T14:28:46Z")

</div>

> [@texnixe](#):
>
> Kirby 3.3.0 has a new [`$collection->when()`](https://github.com/getkirby/getkirby.com/blob/76a4a97fab7316470ce466e9b95d404172c47ad4/content/1_docs/3_reference/4_objects/0_pages/0_when/method.txt) method that makes filtering a lot easier.

I am trying to work with that but I think it is not possible in the way I did.

```
return function($site) {

    $filterBy = get('filter');

    $projects = $site
    ->find('Projekte')
    ->children()
    ->listed()
    ->when($filterBy, function($filterBy) { 
        return $this->filterBy('category', $filterBy); 
    })
    ->when($filterBy == 'prämiert', function() { 
        return $this->filterBy('toggle', true); 
    })
    ->shuffle();

    return [
        'filterBy' => $filterBy,
        'projects' => $projects
    ];
};

```

The first `when()` is working. Now I have a special case where the URL can be:  
`projekte?filter=prämiert`

So I thought, maybe I can say when the `$filterBy` is ‘prämiert’, Kirby could filter the projects for all with toggle set to true. But that is not working. How should I do this?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [December 3, 2020, 2:38pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/16 "2020-12-03T14:38:16Z")

</div>

> [@u13712](#):
>
> ```auto
> ->when($filterBy == 'prämiert', function() { 
> return $this->filterBy('toggle', true); 
> })
> 
> ```

Nope, you can’t put a condition in there, try

```auto
 ->when($filterBy, function($filterBy) { 
        if ( $filterBy === 'prämiert' ) {
            return $this->filterBy('toggle', true); 
        }
    })

```

---

<div class="post-metadata">

**Author:** ![u13712](https://avatars.discourse-cdn.com/v4/letter/u/dfb087/32.png) [@u13712](https://forum.getkirby.com/u/u13712)\
**Post date:** [December 3, 2020, 3:08pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/17 "2020-12-03T15:08:04Z")

</div>

Now I get:

`Error: Call to a member function shuffle() on null`

But only when I click on a filter which worked before. When I click on “prämiert” nothing happens.

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [December 3, 2020, 5:05pm UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/18 "2020-12-03T17:05:41Z")

</div>

Hm, maybe try something else then

```auto
    $projects = $site
    ->find('Projekte')
    ->children()
    ->listed()
    ->when($filterBy, function($filterBy) { 
        if ($filterBy === 'prämiert' ) {
          return $this->filterBy('category', $filterBy)->filterBy('toggle', true); 
        }
        return $this->filterBy('category', $filterBy); 
    })
    ->shuffle();

```

---

<div class="post-metadata">

**Author:** ![u13712](https://avatars.discourse-cdn.com/v4/letter/u/dfb087/32.png) [@u13712](https://forum.getkirby.com/u/u13712)\
**Post date:** [December 4, 2020, 9:16am UTC](https://forum.getkirby.com/t/how-to-filter-by-multiple-parameters-at-the-same-time/16036/19 "2020-12-04T09:16:29Z")

</div>

> [@texnixe](#):
>
> ```auto
> if ($filterBy === 'prämiert' ) {
> return $this->filterBy('category', $filterBy)->filterBy('toggle', true); 
> }
> return $this->filterBy('category', $filterBy); 
> 
> ```

Thank you, this worked:

```auto
if ($filterBy === 'prämiert' ) {
        return $this->filterBy('toggle', true); 
        }
return $this->filterBy('category', $filterBy); 

```
