Search

Since Kirby 2 search is a built-in core feature. You can search all pages of your site or specific sets of pages. In this example you are going to learn how to build a simple search page, how to configure the search and how to display results.

Setting up the search page

The search page can be setup just like any other page. It doesn't matter if it is going to be an invisible or a visible page and the URL doesn't matter as well.

/content
  /1-home
  /2-projects
  /3-about
  /4-contact
  /search
    /search.txt
  /error

The Search Template

Create a new search.php template file in /site/templates. The search template will contain the search form as well as the list of results.

<?php snippet('header') ?>

<form>
  <input type="search" name="q" value="<?= esc($query) ?>">
  <input type="submit" value="Search">
</form>

<ul>
  <?php foreach($results as $result): ?>
  <li>
    <a href="<?= $result->url() ?>">
      <?= $result->title()->html() ?>
    </a>
  </li>
  <?php endforeach ?>
</ul>

<?php snippet('footer') ?>

The Search Controller

As you might have seen in the simple template above, there are two undefined variables so far: $query and $results.

We are going to create a search controller, which handles the actual search and passes those variables back to the template. This will help to keep the template clean and makes it easier to configure the search correctly.

Add a search.php file to /site/controllers Kirby will automatically detect that there's a controller available for the template by search for the same filename.

<?php

return function($site, $pages, $page) {

  $query   = get('q');
  $results = $site->search($query, 'title|text');

  return array(
    'query'   => $query,
    'results' => $results,
  );

};

With the get() method the controller fetches the query from the URL as soon as the search form has been submitted. The query is then passed to the search method of the $site. This searches all subpages recursively. By passing title|text as second argument we define in which fields, the search should be looking for results.

With the returned array we pass the query and the results to the template so we can use those variables there.

Modifying results

In our controller there's plenty of room to improve and modify the results of the search

Added pagination

To avoid a super long list of results, we can easily add pagination by just calling the paginate method on the result set. The passed number is the number of items per page. We can then pass the pagination object to the template as well to get some easier access to its methods. You can find more about the pagination object here.

<?php

return function($site, $pages, $page) {

  $query   = get('q');
  $results = $site->search($query, 'title|text');
  $results = $results->paginate(20);

  return array(
    'query'      => $query,
    'results'    => $results,
    'pagination' => $results->pagination()
  );

};

Search within a specific page

If you want to limit the search to the blog section of your site for example you can just call the seach method on your blog page instead of $site.

<?php

return function($site, $pages, $page) {

  $query   = get('q');
  $results = page('blog')->search($query, 'title|text');
  $results = $results->paginate(20);

  return array(
    'query'      => $query,
    'results'    => $results,
    'pagination' => $results->pagination()
  );

};

Search visible pages only

<?php

return function($site, $pages, $page) {

  $query   = get('q');
  $results = $site->index()->visible()->search($query, 'title|text');
  $results = $results->paginate(20);

  return array(
    'query'      => $query,
    'results'    => $results,
    'pagination' => $results->pagination()
  );

};