Cleaner Code with Controllers

So far, our little project is rather manageable. However, when a project grows, you might find that your template PHP files also grow - in a bad, bloated way. Currently, these template files (and the associated snippets) are the only place where our code lives.

With a growing code base, it will become increasingly difficult to keep our code base cleanly structured. Luckily, Kirby knows the concept of “controllers” to alleviate this pain.

Most modern programming frameworks know the concept of controllers: their job is to unburden the templates - which should concentrate on merely outputting data. Controllers, on the other hand, should concentrate on gathering and preparing this data - and hand it over to the template for display.

Enough of theory: let’s create our first controller!

Controller Boilerplate

The basic mechanics of a controller are rather simple:

a) A controller is an anonymous function that provides access to the $site, $pages, and $page variables for you.
b) You need to return an array with variables that will then be available in your templates.

return function($site, $pages, $page) {
  // do your magic…
  return array('var1' => 'value1’, ‘var2' => ‘value2’);
};

Creating & Naming Controllers

First, we need to create a new “controllers” subfolder inside of “site”. This is the place where all of our controllers will live.

The naming scheme should sound familiar: by creating a “home.php” file in site/controllers, we let Kirby know that it should run this file whenever it renders the template with the same name (“home.php” in site/templates).

Our “home” template can indeed benefit from a supporting controller: in two of its snippets, “newest-post.php” and “recent-posts.php”, the code on the top of the files would better fit into a controller:

// Get all child pages in the "posts" page
$allPosts = $pages->get('posts')->children()->visible();
// we want all but the latest item
$recentPosts = $allPosts->flip()->slice(1);

Let’s move this code (from “recent-posts.php” and the corresponding bits from “newest-post.php”) into our “home.php” controller:

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

  // get all child pages in the "posts" page
  $allPosts = $pages->get('posts')->children()->visible();
  // newest post for the top of the list
  $newestPost = $allPosts->last();
  // recent posts
  $recentPosts = $allPosts->flip()->slice(1);

  // pass variables to the template
  return compact('newestPost', 'recentPosts');
};

The items that our controller returns are now available as variables in our template and snippets (accessible as $newestPost and $recentPosts).

Have a look at the complete code changes of this step to see how much easier it makes our snippets.

Keep controllers as a structuring tool in mind whenever your templates or snippets tend to become cluttered with code.

Giveaways. Cheat Sheets. eBooks. Discounts.
And great content from our blog!

About Us

As the makers of Tower, the best Git client for Mac and Windows, we help over 100,000 users in companies like Apple, Google, Amazon, Twitter, and Ebay get the most out of Git.

Just like with Tower, our mission with this platform is to help people become better professionals.

That's why we provide our guides, videos, and cheat sheets (about version control with Git and lots of other topics) for free.