🚚 How to migrate to Kirby Tips & tutorials
Skip to content

Sharing templates across blueprints

Content files, blueprints, templates and controllers in Kirby are all connected through their filenames: a content file blogarticle.txt will use the blogarticle.yml file when it is opened in the Panel, and will be rendered with the blogarticle.php template in the frontend using an blogarticle.php controller to load the logic if available.

If a template with the same filename as the content text file doesn't exist, Kirby will fall back to the required default.php template.

So, the easiest way to share a template between pages with different blueprints would be to use the default.php template.

However, there might be situations where this is not desired, like when the default template should really be the last fallback template, or if you need multiple shared templates.

The templates extension to the rescue. With the template extension, Kirby allows you to register templates in a plugin. The templates extension accepts an array of key/value pairs, where the key is the name of the template and the value the path to the file in your plugin folder:

/site/plugins/your-plugin/index.php
<?php

use Kirby\Cms\App as Kirby;

Kirby::plugin('cookbook/shared-templates', [
    'templates' => [
        'blog' => __DIR__ . '/templates/blog.php',
    ]
]);

How can we leverage this extension to use the same template for multiple page types? By simply assigning the same file to multiple template names, like this:

/site/plugins/your-plugin/index.php
<?php

use Kirby\Cms\App as Kirby;

Kirby::plugin('cookbook/shared-templates', [
    'templates' => [
        'jobs'   => __DIR__ . '/templates/grid.php',
        'events' => __DIR__ . '/templates/grid.php',
        'news'   => __DIR__ . '/templates/grid.php',
        //…
    ]
]);

If you ever decide that one of the page types should get a different template, you can either change this in the plugin, or add a new template in the /site/templates folder.

An example: Assuming the jobs page type should get its own template, place a jobs.php template into /site/templates.

You can also use this setup to register the same controller for these templates. Note that the syntax for registering controllers is different from registering templates:

/site/plugins/your-plugin/index.php
<?php

use Kirby\Cms\App as Kirby;

Kirby::plugin('cookbook/shared-templates', [
    'templates' => [
        'jobs'   => __DIR__ . '/templates/grid.php',
        'events' => __DIR__ . '/templates/grid.php',
        'news'   => __DIR__ . '/templates/grid.php',
        //…
    ],
    'controllers' => [
        'jobs'   => require __DIR__ . '/controllers/grid.php',
        'events' => require __DIR__ . '/controllers/grid.php',
        'news'   => require __DIR__ . '/controllers/grid.php',
        // …
    ]
]);

And it also works for page models:

/site/plugins/your-plugin/index.php
<?php

use Kirby\Cms\App as Kirby;

class BasePage extends Page
{
  public function helloWorld()
  {
    return 'Hello World';
  }
}

Kirby::plugin('cookbook/shared-templates', [
    'templates' => [
        'jobs'   => __DIR__ . '/templates/grid.php',
        'events' => __DIR__ . '/templates/grid.php',
        'news'   => __DIR__ . '/templates/grid.php',
        //…
    ],
    'controllers' => [
        'jobs'   => require __DIR__ . '/controllers/grid.php',
        'events' => require __DIR__ . '/controllers/grid.php',
        'news'   => require __DIR__ . '/controllers/grid.php',
        // …
    ],
    'pageModels' => [
        'jobs'   => 'BasePage',
        'events' => 'BasePage',
        'news'   => 'BasePage',
        // ...
    ],
]);

We define a Base model, and assign it to different page model names.

In a real world example, your class would most probably go into a separate file, for details see the page models reference.

Author