Controllers
- The controllers directory
- Default controller
- Creating a controller
- A real world example
- Arguments from the router
Templates should contain as little code as possible to separate logic and form. With template controllers you can add more logic to your templates without messing up your markup.
The controllers directory
Controllers go into /site/controllers
. Please create the directory if it's not there yet. Controllers are named exactly like the templates they belong to:
Template | Controller |
---|---|
/site/templates/article.php | /site/controllers/article.php |
Kirby will automatically load the controller for your template if it can find one.
2.3.0 +
Default controller
You can also have a default page controller: It works like a normal page controller. You only have to add it as site/controllers/site.php
. Be aware that the default controller only works as a fallback if no specific page controller for the template exists. It is not loaded in addition to the template-specific one.
Creating a controller
The basic code for a controller is very simple. It's an anonymous function, which receives the $site, $pages and $page variables as arguments and should return any number of variables as associative array, which you want to pass to the template.
<?php
return function($site, $pages, $page) {
return array(
'foo' => 'my first template variable',
'bar' => 'my second template variable'
);
};
In this case the $foo
and $bar
variables will be available in the corresponding template.
A real world example
A typical example when a controller can come in handy is a blog template. Fetching the right articles can take a couple lines of code and it's much nicer to wrap this in a controller. So let's create /site/templates/blog.php
and /site/controllers/blog.php
The controller
The controller will take care of fetching the right articles and add pagination to them. It will then pass an $articles
variable to the template to keep it nice and clean.
<?php
return function($site, $pages, $page) {
// get all articles
$articles = $page->children()->visible()->flip();
// add a tag filter
if($tag = param('tag')) {
$articles = $articles->filterBy('tags', '=', urldecode($tag), ',');
}
// add pagination
$articles = $articles->paginate(20);
// create a shortcut for pagination
$pagination = $articles->pagination();
// pass $articles and $pagination to the template
return compact('articles', 'pagination');
};
The template
With such a controller, the template can be super clean. A foreach loop for the articles and the prev/next pagination and you're done.
<?php snippet('header') ?>
<?php foreach($articles as $article): ?>
<!-- the code for each article goes here -->
<?php endforeach ?>
<nav class="pagination">
<?php if($pagination->hasPrevPage()): ?>
<a href="<?= $pagination->prevPageUrl() ?>">previous articles</a>
<?php endif ?>
<?php if($pagination->hasNextPage()): ?>
<a href="<?= $pagination->nextPageUrl() ?>">next articles</a>
<?php endif ?>
</nav>
<?php snippet('footer') ?>
Arguments from the router
If you are working with additional routes and you want to access the arguments from the router in your controller you can use the fourth argument to access an array of router arguments.
<?php
return function($site, $pages, $page, $args) {
// $args contains all arguments from the current route
};