Frontend search find pages by content from linked pages (via pages field)

Hi there,

I’ve got a section of pages that are persons and another section which are projects.

Inside the projects there’s a pages field that can link to one or more of the persons pages.

Now I have a frontend search that works fine so far. But it does not find projects that include a specific person. I presume that is because the content of the linked persons page is not indexed, since it’s only an id or a list of ids.

Is there an easy way to make the search work for at least the name or even slug of the linked person in a project?

In other words: The frontend user needs to be able to find projects that include a specific person when searching for the person’s name. Currently this does not work, because the search is unaware of any content linked in the projects pages field.

Thanks for any hints!

Alexander

You could create a model for the projects page, and inside that mode, use the setContent() method to add some additional content virtually. This additional content could for example be a json_encoded array of the relevant data for each person, e.g.

	protected function setContent(array|null $content = null): static
	{
		$content = array_merge((array)$content, [
			'additional' => json_encode($this->fieldName()->toPages()->toArray()),
		]);
		
		parent::setContent($content);
		
		return $this;
	}
}

At least in my quick test this worked as expected. Don’t know if there are any downsides to it.

Thank you Sonja,

I tried adapting this, but it results in a blank page with a PHP error in the logs:

[19-Feb-2026 11:20:18 UTC] PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 32768 bytes) in /…/kirby/vendor/filp/whoops/src/Whoops/Util/Misc.php on line 1

The code is almost the same as yours, here’s the full model file:

<?php

class ProjektPage extends Page {
  protected function setContent(array|null $content = null): static
	{
		$content = array_merge((array)$content, [
			'additional' => json_encode($this->ansprechpartner()->toPages()->toArray()),
		]);
		
		parent::setContent($content);
		
		return $this;
	}
}

Maybe I am overlooking something obvious? Looks like the recursive setContent() is the initial problem?

And does setContent() override the full Page or merely add the data?

OK, with some (a lot of) help from @nilshoerrmann I got this working with a different approach. In the search controller the projects are now modified and rebuilt into a collection:

$virtual = [];
  $projects = $site->find('projekte');
  foreach($projects->children()->listed() as $project) {
    
    // get person names from linked persons title field and store them into a simple string
    $apString = '';
    foreach ($project->ansprechpartner()->toPages() as $ap) {
      $apString = $apString . $ap->title() . ' ';
    }
    
    // rebuild the page object with all neccessary fields for the search function
    $virtual[] = [
      'slug' => $project->slug(),
      'url' => $project->url(),
      'template' => $project->template(),
      'content' => [
        'title' => $project->title(),
        …
        'ansprechpartner' => $apString,
      ]
    ];
  }
  // create a proper page collection
  $results = Pages::factory($virtual, $projects);

  // then search all the fields incl. the newly created string
  $results = $results->search($query, 'title|uber|sub|kurz|text|ort|kenngroessen|vorname|nachname|ansprechpartner'); 

:sweat_smile: