Listing all the pages in every layer – $site->index()->groupBy()?

Hey there,

I’m in the process of adding a “page link” functionality to the Visual Markdown Editor by @DieserJonas.
Some of my clients asked for a more visual way of selecting the page for a page link. Otherwise you have to copy the URI by hand.

That’s how it looks right now:

Anyway, I seem to over-complicate the process of listing every level of pages grouped by their parents.
I don’t really want to have over 100 lines of code just to go through all the children, and their children, and their children, … and then somebody adds a fifth layer to their Kirby site.

I tried to use the ->groupBy() function on the $site->index() variable. But that didn’t work. The children will have to be in the parents element and I couldn’t figure that out.

What’s the best way to list an infinite amount of pages and all of their descendants? I’m sure there’s an easy way.

Thank you!


Have a look at the treemenu snippet:, you should be able to adapt that to your purpose by using the depth() function.

If you want to learn more about this programming concept: It is called recursion.

Thank you! I knew there was a Kirby-like solution :+1:

Sorry, but I’ll have to ask something concerning this again. :disappointed:

The treemenu script uses a snippet to call the function again. But I can’t use a snippet, since I’m working on a custom field. Thanks to @lukasbestle I knew what these recursive functions are called, though. And I could google it. So I tried to declare a PHP function with a variable and call it when I want to list the next layer. It won’t work no matter what I try.

That’s what it looks like:

$subpages = site()->children();
function listpages($subpages) {
  <? foreach ($subpages as $subpage): ?>
      <div class="page">
        <div class="pagename">
          <span class="name"><?= $subpage->title() ?></span>
        <? if($subpage->children()->count() > 0): ?>
          <div class="subpages">
            <? return listpages($subpages = $subpage->children()); ?>
        <? endif ?>
  <? endforeach ?>

I’d greatly appreciate any help. Thank you!


Ok, I figured it out myself.
For everyone else with the same problem:

You (obviously) can not display HTML content inside the curly quotes of the PHP function. That’s how it looks fixed:

$subpages = site()->children();
function listpages($subpages) {
  foreach ($subpages as $subpage) {
    echo('<div class="page">');
    echo('<div class="pagename">');
    echo('<span class="name">' . $subpage->title() . '</span>');
    echo('<div class="subpages">');
    if($subpage->children()->count() > 0) {
     listpages($subpages = $subpage->children());
listpages($subpages = site()->children());

Well, I think the main issue was that you didn’t call the function in the first code snippet you posted. The last line of the second one does call it, so that’s why it works now. :smiley:

Yeah, I didn’t even call the function in the first code snippet. But that was because everytime I called it, the panel broke.

But now it works. Thank you!

Do you have any plan to open source this functionality? I would be really interested!

The repo is on GitHub

The most recent integration of this page link functionality is in my “Enhanced Textarea” field:

It works exactly the same.

Thanks for letting us know :slight_smile: Could you maybe put a note on the old version that links to the new?

It’s not exactly “old”. It was an extension of the Visual Markdown Editor, now it’s also an extension for the regular textarea field. So, both have the right to live :grin:

1 Like

Ah ok, thanks for clarifying. I thought maybe the Visual Markdown Extension Edition was no longer under development.