Foreach Page but only if linked to another page?

Hello,
I’m using Categories as Pages. I’m creating the individual Category pages and listing all of the Notes attached to it.
<?php foreach (page('notes')->children()->listed()->sortBy('date', 'desc')->limit(10) as $note): ?>
How would adding the filterBy work here?
Essentially, showing only Notes that are linked to a certain Page, I think.

How are they linked, via a pages field where you select one of the category pages?

Exactly. I’ve been using two methods to compare their utility. Either with a

fields:
  category:
    type: pages
    options: query
    query: site.find("notes").children

Or with

fields:
  category:
    type: select
    options: query
    query: site.find("notes").children
<?php 
$categoryNotes = page('notes')->children()->listed()->filterBy('category', $page->id())->sortBy('date', 'desc')->limit(10);
foreach ($categoryNotes as $note) {
  // code here
}

Note that $page->id() in the above snippet has to be replaced with what is actually stored in the file, I think it’s the ID by default but please double check.

1 Like

This is working very well. Thank you! I left the $page->id() alone and it worked.
Of note, this method works if you’re defining a Field using the select type in your blueprint, but using it as a pages Field type, it does not.
Presumably since you can select only one using select, but multiple with pages?

No, because the pages field stores its stuff in yaml format, to cater for that, you have to use the filter($callback) method (still assuming only one entry):

$categoryNotes = page('notes')->children()->listed()->filter(function($child) use($page) {
  if (($category = $child->category()->toPage()) && $category === $page) {
    return $child;
  }
})->sortBy('date', 'desc')->limit(10);

foreach ($categoryNotes as $note) {
  // code here
}

If you link to multiple categories in your pages field, you would have to adapt again.

1 Like

Oh, my. Thank you.
So, when multiples are used, you’d have to explode or pluck it from an array? I’m only guessing, I’m a noob.
Update: I’m not sure the code is correct. There seems to be an extra ), or something above.
Update2: I am also exploring the multiselect method instead of select Field.

Multiselect:

$categoryNotes = page('notes')->children()->listed()->filter(function($child) use($page) {
  $categories = $child->category()->toPages(','); // get a collection of pages from a comma separated list of page IDs
  return $categories->has($page->id());
})->sortBy('date', 'desc')->limit(10);

Pages field with multiple pages

$categoryNotes = page('notes')->children()->listed()->filter(function($child) use($page) {
  $categories = $child->category()->toPages();
  return $categories->has($page->id());
})->sortBy('date', 'desc')->limit(10);

There’s only a small difference between these to in how it converts the category field content to pages.

In the example above, a closing curly brace was missing, I’ve corrected it.

1 Like

This is working so well. I finally see the logic of the code, too. Thanks so much for your help, Sonja. Thanks for working on this on the weekend. Cheers! :wink: