Filtering pages by checking if multiselect field contains title of another/current page?

I’m trying to filter a collection of pages by the existence of another page’s title in a multiselect field (in the pages being filtered).

Say I have a type of page called Productions with children called Production. Each Production has a multiselect field which allows selecting one or more Actors, which are their own type of page, queried in the multiselect field.

When rendering an Actor page, how can I query all Production pages which have the current Actor selected in their Actors multiselect field?

I tried using the current page’s/actor’s title in a filter callback, which doesn’t work because it seems the $page variable is not available inside the callback:

# multiselect field in production blueprint…

actors:
  type: multiselect
  label: Actors
  options: query
  query:
    fetch: site.find('Actors').children.listed
    value: "{{ page.title }}"
  icon: users
  width: 1/2

# in actor page or controller...

$productions = page('Productions')->children()->listed()->filter(
                 function($prod) {
                   return in_array($page->title(), $prod->actors()->split());
                 }
               );

Two ways to fix this:

$productions = page('productions')->children()->listed()
  ->filter(function($prod) use($page) {
        return in_array($page->title(), $prod->actors()->split());
  }
);
$productions = page('productions')->children()->listed()
  ->filter(fn ($prod) => in_array($page->title(), $prod->actors()->split(',')));

Wondering why you are storing the title as reference instead of the id, as the title is even more likely to change than the id. And a multiselect instead of a pages field (but that’s probably because you are storing the title which would not be possible with the pages field.

Ah, the use($page) method is what I was missing, thank you.

Wondering why you are storing the title as reference instead of the id…

Because I need to output the actor’s title in the production’s template. If I set the multiselect’s value to page.id, can I not output only the id and not the title?

No. You are much more versatile with the id. By calling toPages() on the field that stores the ids, you get a collection of pages you can then loop through and you have access to every page property, not just the title:

$actors = $page->actors()->toPages(','); // when using the pages field, you would remove the comma attribute
foreach ($actors as $actor) {
  echo $actor->title(); // or whatever else
}

Your filter could then look like this:

$productions = page('productions')->children()->listed()
  ->filter(fn ($prod) => $prod->actors()->toPages()->has($page)); // or with a comma passed to `toPages()` in your multiselect variant.

Cool, thank you, I adopted your solution