🚀 A new era: Kirby 4 Get to know
Skip to content

Snippets

Snippets are smaller blocks of code that you can reuse across templates. They are ideal for keeping your templates clean and maintainable.

Screencast

Make your life easier with snippets

A great way to clean up your templates and reuse parts of your templates multiple times.

Use cases

Typical examples in the Starterkit are the header.php, footer.php and menu.php snippets that are used in every template.

Snippets are stored in the /site/snippets folder and like templates, they have the extension .php.

Using snippets

Kirby's snippet() helper function lets you include snippets into your templates:

Snippet In your template
/site/snippets/header.php <?php snippet('header') ?>
/site/snippets/menu.php <?php snippet('menu') ?>
/site/snippets/footer.php <?php snippet('footer') ?>

If you want to organize snippets in subfolders, you can do so. In that case, you have to pass the path to the snippet to the snippet function:

Snippet In your template
/site/snippets/basics/header.php <?php snippet('basics/header') ?>

Let's clean up a template

The most basic use case for snippets is splitting the header and footer into separate snippets. Let's explore how we can break up the basic template from the last section and make parts of it reusable:

/site/templates/default.php
<html>
<head>
  <meta charset="UTF-8">
  <meta name="description" content="<?= $site->description() ?>">
  <meta name="keywords" content="<?= $site->keywords() ?>">
  <title>
    <?= $page->title() ?> | <?= $site->title() ?>
  </title>
</head>
<body>

  <header>
    <h1>
      <a href="<?= $site->url() ?>">
        <?= $site->title() ?>
      </a>
    </h1>
  </header>

  <main>
    <h1><?= $page->title() ?></h1>
    <?= $page->text() ?>
  </main>

  <footer>
    <p class="copyright"><?= $site->copyright() ?></p>
  </footer>

</body>
</html>

The code above looks fine as long as we just have a single template. But with every template we add, we would have to repeat the same stuff over and over again. What if we wanted to make a change to the header or footer? We would have to touch every single file.

Well, we don't want to waste our precious time, so let's clean this up a bit!

/site/snippets/header.php
<html>
<head>
  <meta charset="UTF-8">
  <meta name="description" content="<?= $site->description() ?>">
  <title>
    <?= $page->title() ?> | <?= $site->title() ?>
  </title>
</head>
<body>

  <header>
    <h1>
      <a href="<?= $site->url() ?>">
        <?= $site->title() ?>
      </a>
    </h1>
  </header>
/site/snippets/footer.php
<footer>
    <p class="copyright"><?= $site->copyright() ?></p>
  </footer>

</body>
</html>

Now that we have separated those parts, the final template looks very neat:

/site/templates/default.php
<?php snippet('header') ?>

  <main>
    <h1><?= $page->title() ?></h1>
    <?= $page->text()->kirbytext() ?>
  </main>

<?php snippet('footer') ?>

No matter how many more templates we will add to our site, the header and footer part are now only two lines of code. All we need to modify is the main part of the template.

Passing variables to snippets

Sometimes it is useful to pass a variable to a snippet.

<?php snippet('mysnippet', ['title' => 'Hello!']) ?>

With the above code, /site/snippets/mysnippet.php will receive a title variable with the content "Hello!" that we can now echo in our snippet:

/site/snippets/mysnippet.php
<?= $title ?>

Snippets always receive the following variables from Kirby:

Variable Type Value
$slot Kirby\Template\Slot|null Contents of the default slot if it exists
$slots Kirby\Template\Slots Collection of all slots

You can read more about the slots feature below.

Real life example: list of blog articles

The template

<?php snippet('header') ?>

<main>

  <h1>Blog</h1>

  <?php foreach($page->children() as $article): ?>
  <?php snippet('article', ['article' => $article]) ?>
  <?php endforeach ?>

</main>

<?php snippet('footer') ?>

In this example, we pass the $article variable (which is a page object) to the snippet and can then fetch the data from that page in our snippet:

The article.php snippet

/site/snippets/article.php
<article>
  <h1><?= $article->title()->html() ?></h1>
  <time><?= $article->date()->toDate('d/m/Y') ?></time>
  <?= $article->intro()->kirbytext() ?>
  <a href="<?= $article->url() ?>">Read more…</a>
</article>

Pro tip

Because the variable name inside the template and snippet is the same, we can use PHP's compact() function to make the code shorter. This is especially useful if you want to pass multiple variables with their current name:

<?php snippet('article', compact('article')) ?>

The compact() function takes the variable values from the current scope and compacts them into an array. So it's the same as writing ['article' => $article].

Passing slots to snippets

Screencast

Snippets with slots

Check out our extensive screencast to learn more about snippets with slots.

Data variables are useful if you want to pass whole objects (like the page object in the example above) or other values that you have already stored in variables.

Sometimes, passing data isn't enough, for example when you want to pass full code blocks into snippets and output them inside the snippet. For this you can use snippets with slots:

<?php snippet('article', slots: true) ?>
  <?php slot('header') ?>
    <h1>This is the title</h1>
  <?php endslot() ?>

  <?php slot('body') ?>
    <p>This is some body text</p>
  <?php endslot() ?>
<?php endsnippet() ?>

The contents of each slot are captured and passed to the snippet in the $slots variable:

/site/snippets/article.php
<article>
  <?php if ($header = $slots->header()): ?>
  <header>
    <?= $header ?>
  </header>
  <?php endif ?>

  <?= $slots->body() ?>
</article>

The names header and body are just examples. You can use as many slots as you like and give them names that fit your use case. Every slot that isn't passed from the template will be set to null.

Default slot

Code that is printed directly between the snippet() and endsnippet() calls is captured into the default slot:

<?php snippet('button', slots: true) ?>
  This is the button text.
<?php endsnippet() ?>

The default slot can be accessed with the $slot variable or with $slots->default():

/site/snippets/button.php
<button>
<?= $slot ?>
</button>

You can combine the default slot with named slots by calling the slot() function without a name:

<?php snippet('form', slots: true) ?>
  <?php slot() ?>
    <label for="email">Email address:</label>
    <input type="email" id="email" name="email">
  <?php endslot() ?>

  <?php slot('submit') ?>
    <input type="submit" value="Subscribe">
  <?php endslot() ?>
<?php endsnippet() ?>
/site/snippets/form.php
<form action="" method="POST">
  <?= $slot ?>

  <?php if ($submit = $slots->submit()): ?>
  <?= $submit ?>
  <?php else: ?>
  <input type="submit" value="Submit">
  <?php endif ?>
</form>

Layout snippets

If a snippet is still open at the end of the template, Kirby automatically closes it. This can be used for layout snippets, i.e. snippets that contain a base layout that is shared between templates:

<?php snippet('layout', slots: true) ?>

<?php slot('footer') ?>
This is a custom footer.
<?php endslot() ?>

<?php slot() ?>
<h2>And this is the main content</h2>
<p>With some text.</p>
<?php endslot() ?>
/site/snippets/layout.php
<html>
<head>
  <meta charset="UTF-8">
  <meta name="description" content="<?= $site->description() ?>">
  <meta name="keywords" content="<?= $site->keywords() ?>">
  <title>
    <?= $page->title() ?> | <?= $site->title() ?>
  </title>
</head>
<body>

  <header>
    <h1>
      <a href="<?= $site->url() ?>">
        <?= $site->title() ?>
      </a>
    </h1>
  </header>

  <main>
    <?= $slot ?>
  </main>

  <footer>
    <?php if ($footer = $slots->footer()): ?>
    <?= $footer ?>
    <?php else: ?>
    <p class="copyright"><?= $site->copyright() ?></p>
    <?php endif ?>
  </footer>

</body>
</html>

Combining slots with data

If you want to pass a variable in addition to slots, you can combine slots with the $data parameter:

<?php snippet('button', ['class' => 'large'], slots: true) ?>
  This is the button text.
<?php endsnippet() ?>
/site/snippets/button.php
<button class="<?= $class ?>">
<?= $slot ?>
</button>

Nesting snippets

You can nest snippets (with slots and/or data) inside slots of other snippets:

<?php snippet('article', slots: true) ?>
  <?php slot('body') ?>
    <p>This is some body text</p>

    <?php snippet('figure', ['image' => $page->image()]) ?>

    <?php snippet('button', slots: true) ?>
      This is a button.
    <?php endsnippet() ?>
  <?php endslot() ?>
<?php endsnippet() ?>

Snippet alternatives

You can define an array of snippet alternatives if the first snippet cannot be found:

<?php snippet(['snippet1', 'snippet2', 'snippet3']) ?>

This is useful if you want to provide fallbacks for a snippet based on page input, in case the snippet does not exist:

<?php snippet(['articles/' . $page->postType(), 'articles/default']) ?>

Assigning a snippet to a variable

The snippet() function has a third, optional parameter of type boolean. If set to true, Kirby returns the parsed content instead of directly echoing it. With this option, snippets can be used in a variety of situations, not just inside page templates:

$emailBody = snippet('email', $data, true);

If you use the slots parameter, the snippet() helper always returns the snippet object. In this case you can use the $snippet->render() method to pass the slots to the snippet, render the snippets contents and store them in a variable:

$emailBody = snippet('email', $data, slots: true)->render(slots: [
  'offer' => 'We have prepared a special deal just for you...'
]);

More information