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 Actorsmultiselect 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());
}
);
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.
I see here that the toPages() on a type: multiselect field of pages requires the ',' within the parens as seen above to make it work in the foreach loop. Check.
So, I like using the Pages field type instead of the multiselect, allowing me to click through to that page while still in this panel page to make edits on that page. Perfect. If that doesn’t matter, then a multiselect should work find for you.
My question isn’t about filtering, but as you can see it’s loosely related:
Yes, of course, I prefer to consult the documentation first. Viewing the template section of these pages and neither mention that having a ‘,’ in a toPages() to get them to render properly. Searching the forum landed me here. This info helped me to render a link list to the selected pages using the pages type.
I just don’t know enough PHP is all.