Share the content of a controller across multiple templates
Controllers are an excellent tool to keep your templates and blueprints clean and "logic free". For better or worse, a controller is tied to a specific template and this can sometimes be a problem when we want to share the same data across all our templates.
Luckily for us, creating a shared controller is an easy task in Kirby 3.
We'll use the
<meta name="description"> tags as an example. The easiest way to add those two tags to our site would be to add them directly into the
header.php snippet. Something like this:
That's a perfectly fine and reasonable solution. But what if we want to show a slightly different title for the homepage for example?
This is already starting to look ugly and things will only get messier if we start adding more logic or other tags. It then makes sense to move the logic from the snippet into a controller.
Let's do that.
The first thing we need to do is set up our default controller. To do that we'll make use of the
site.php controller that will also act as a fallback when no controller is found for a particular template.
Now that the logic to fetch the correct data has been moved inside the controller we can simplify the
Excellent, this is already looking a lot cleaner. Now we need to implement the different logic to create the
<title> tag for the homepage. To do that we'll use a
home.php controller. You'd think that doing something like this would be enough to achieve our goal.
But if we do that and we navigate to our homepage we'll get presented with an error.
Undefined variable: metaDescription
That's because we now have a controller for the homepage, and Kirby will use that instead of our fallback one. An intuitive solution would be to simply copy and paste the same line of code from the
site.php controller into the
home.php controller but that goes against the DRY principle.
This is where the concept of the shared controller becomes useful. Rather than copy and pasting the same code, we'll first use the
$kirby->controller() method to get the data from the
site.php controller and store it in a variable.
Then we'll overwrite the content of our title tag with the different bit of logic we want to use for the homepage.
And finally, we'll merge the content and return it as an array that will then get passed to the template
Be careful, when merging the two arrays, to pass the
$shared array as the first parameter to the
a::merge() function. This is important because otherwise your new data won't overwrite the content coming from the default controller.
home.php controller will look like this:
And that's it. We now have a place to store all the data that is shared among all our templates and we have a way, using controllers, to overwrite what needs to be overwritten on a template by template basis.
In this example we've used the
site.php controller to share content across the entire site but the same concept can be adapted to share content across a more local scope.
For example, in a blog you could have different controllers for different type of blog posts...
...and you can leverage the method described in this guide to share the content of the
post.php controller with the other controllers.
To do that you need to pass the correct controller name to the
controller() function and you're done.
This cookbook recipe was written by Manu Moreale.