Params based on custom filters give no result

Hi there!

I’ve been struggling for 48 hours on a controller function which doesn’t work as expected. Could someone help me please?

Context
The website lists a huge amount of books, that can be filtered with params (like theme:, collection:, serie:, etc). On the panel side, the client can customize the behavior of each filters/params.
Everything works like a charm… except for the age: filter.

Issue
The client creates a new Age filter through a structure field, gives it a name like Young adults, and chooses in a multiselect field one or more ‘ages’ which are used to filter the entire collection of books, like From 11 years old, From 12 years old, Tout public, etc.
This way, when a visitor clicks on the filter Young adults, the URL ends with age:Young+adults… and the books which have age: From 11 years, From 12 years old should be displayed… but nothing is displayed right now!

Here is a how the catalog blueprint looks like (partially):

filters:
  type: structure
  fields:
    agerelated:
      type: multiselect
      options: query
      query:
        fetch: page.age.toStructure
        text: "{{ structureItem.text }}"
        value: "{{ structureItem.text }}"
    filterlabel:
      type: text

And the output:

Filters:
- 
  agerelated: Dès 18 mois, Dès 2 ans, Dès 3 ans
  filterlabel: 0-3 ans
- 
  agerelated: >
    Dès 3 ans, Dès 4 ans, Dès 5 ans, Dès
    6 ans
  filterlabel: 3-6 ans
- 
  agerelated: Tout public
  filterlabel: Tout public

Controller
Here is the logic behind my controller:

  1. Get the age param and urldecode it
  2. Go through the filters structure and find the entry related to this param based on the filterlabel
  3. Get all the selected options from the list (agerelated)
  4. Filter the books from the collection that have the corresponding age defined
  5. Paginate, etc
if($age = urldecode(param('age'))){
  foreach($page->filters()->toStructure() as $filter){
    if($filter->filterlabel() == $age){
      $agesrelated = $filter->agerelated()->split();
      $books = $kirby->collection('books)->filter(function ($book) {
        if(in_array($book->age(), $agesrelated)){
          return $book;
        }
      });
    }
  }
  $books = $books->paginate(12);
  $pagination = $books->pagination();
  return compact('books', 'book', 'pagination');
}

When I manually replace $agesrelated in the function by [‘Tout public’] or [‘Dès 12 ans’, Dès 13 ans’], the books are displayed correctly. And when I dump $ages I have this array:

Array
(
    [0] => Dès 10 ans
    [1] => Dès 11 ans
    [2] => Dès 13 ans
    [3] => 11-14 ans
    [4] => 12-14 ans
)

I’ve tried to implode it, play around with the overall function, tried the search method, etc, and my brain is probably boiling right now. So if anyone here has an idea of what is wrong, please shoot.

Thank you :hugs:

First of all there is a missing closing quote after books, and secondly, you have to pass the $agesrelated variable to the filter callback:

$books = $kirby->collection('books')->filter(function ($book) use($agesrelated) {
        if(in_array($book->age(), $agesrelated)){
          return $book;
        }
      });

Also, what does $book->age() contain? Just one age or is that a list of ages?

1 Like

WOW ! I didn’t expect this issue to be solved so quickly!
YOU ARE A-M-A-Z-I-N-G !!

Passing the variable to the filter callback was the solution. The closing quote was a mistype in my post.

$book->age() contains only one age, selected from a list defined in the catalog/parent page.

:kissing_smiling_eyes:

1 Like