Grouping by structure field value

OK, expanding from my other thread, how do I group child pages by the value of a field in a structure field? I’ve read Grouping collections | Kirby CMS and Fetching field options | Kirby CMS but none of these seem to apply to my use case.

So, for context: I have a list of category names and “slugs” stored in a structure field on the parent page:

kategorien:
  type: structure
  label: Kategorien
  fields:
    name:
      type: writer
      nodes: false
      marks:
        - bold
        - italic
      help: Der öffentlich sichtbare Name der Kategorie; Textformatierungen sind möglich.
      required: true
    kategorie_id:
      type: text
      label: ID
      help: Reiner Text, nur Kleinbuchstaben, Zahlen, Unter- und Bindestriche erlaubt.
      required: true

On child pages, there is a select to select the appropriate category:

kategorie:
  type: select
  required: true
  options:
    type: query
    query: page.parent.kategorien.toStructure
    text: "{{ item.kategorie_id }}"
    value: "{{ item.kategorie_id}}"

In the template on the parent page, I want to group by category and show the formatted category name as heading but I’m stuck on how to achieve this. I tried:

$kategorien = $page->children()->listed()->group(function($kategorie) {
	$kat = $kategorie->kategorie();
	return $kat;
});

but that only returns an array with the category ID because that’s how it’s saved according to the child page blueprint. I can’t use the formatted value in the select, though, because select options can only have plain text. So, how would I get the content of the category name field on the parent page?

You don’t group by the structure field value, but by the value stored in the kategorie field (kategorie_id), like normal, then when rendering the value, you fetch the name that corresponds to that value from the structure field (findBy)

Sorry, I think there is a slight misunderstanding. I can group the pages alright but getting the category name for the group headings is the issue. As far as I can see, there is no findBy() method for structure fields. This is the structure field array when doing $page->kategorien()->yaml():

Array
(
    [0] => Array
        (
            [name] => <strong>my</strong><em>formatted</em><strong>text</strong></p>
            [kategorie_id] => kategorie_1
        )

    [1] => Array
        (
            [name] => <p><strong>my</strong><em>other</em><strong>category</strong></p>
            [kategorie_id] => kategorie_2
        )

)

I guess I need to access the name field value of the structure field inside the category loop to print that value, but unfortunately the structure field array isn’t really an associative array and my PHP knowledge is limited. :frowning:

This returns an array which you cannot access with findby, if you use toStructure() you get a collection which you can search with findBy

Thanks, after a lot of brain racking and hair pulling I finally got it. I didn’t even know a $structure object/class exists, I never got into these corners of the documentation, let alone understand anything. This is something I’ll sit in front of next time, having forgotten everything and having to start from zero again when I look at this in a year from today. :face_with_diagonal_mouth:

For reference, this is the solution:

$kategorien = $page->kategorien()->toStructure();
$gruppen = $page->children()->listed()->groupBy('kategorie');
foreach($gruppen as $kategorie => $unterseiten):
	$kategoriename = $kategorien->findBy('kategorie_id', $kategorie)->name();
	…
	echo($kategoriename);