A different approach to the Kirby content() method?

If you work with Kirby you are familiar with the concept of creating fields in a page blueprint and accessing it in your page template. Usually you end up with something like this:

<?= $page->myField() ?>

As long as your field name does not match a reserved word you’re fine. But as soon as your field name has the same name as an existing page method you need to make use of the content() method (and everything is fine again).

<?= $page->content()->myField() ?>

Since I use custom page methods on a regular basis, I prefer to use the content() method for every page field. No matter if there’s a naming conflict or not. In this way it is easier to me to differentiate between page methods and fields.

<?= $page->url() ?>
<?= $page->customPageMethod() ?>
<?= $page->content()->myField() ?>

Unfortunately it requires more typing and (in my opinion) it's a bit harder to read as well.

Introducing a $content variable

Lately I had the idea to create a custom $content variable and use it across all page templates. The right place for additional variables for your page template is a controller. Every page template can have its own controller. But there is also a general site controller which is useful if multiple templates share the same logic.

/site/controllers/site.php

<?php

return function ($page) {
  return [
    'content' => $page->content(),
  ];
};

With this few lines it is now possible to use a $content variable as a replacement of $page->content() across all page template. The page template example from above can be be changed to the following. It might look unusual at first but I think i’ll give it a try.

<?= $page->url() ?>
<?= $page->customPageMethod() ?>
<?= $content->myField() ?>

Please be aware that, as soon as you create a custom controller for a single page type, you need to define the $content variable again. Since it’s just a single line of code, I think it’s not a big deal. If you have more variables you want to share, check out this tutorial about how to create a shared controller setup by Manu Moreale. By the way, with Kirby 5 the shared controller setup will no longer be necessary because the general site controller will automatically be merged.

One more thing …

As Florens mentioned on Mastodon, this approach only works while $page represents the current page, because the variables defined within the controller are only available in the corresponding page template. That’s a valid point you have to keep in mind.

But in combination with custom view modes it still might be a way to go because if you use these view modes consequently it will probably reduce the amount of situations where $page is not the current page. I will try both in combination and might come back with a report of my findings.

Sources


CMS Kirby PHP #Template

Replies

  • moinframe | Justus

    @flokosiol Ohh, not a bad idea. I always found it a bit confusing, especially for people new to Kirby, to understand which methods are real methods and which are just fields. Might try your approach!

  • Flo

    @moinframe Thanks for your reply! Would love to hear from you again after some time working with it. Even if you go back to the default system. I‘m always interested in different point of views. 🙌

  • Felix Niklas
  • Florens Verschelde

    @flokosiol @getkirby Interesting, but I think in my last big Kirby project, more often than not I was working with pages which are not the current page (any page from a list: navigation, child pages, related pages, etc.). So always minding when I can use `$content` vs `$item->content()` would be more confusing than helpful.

    With time I kinda shy away from using the injected `$kirby`, `$site` and `$page` variables, often using `kirby()`, `kirby()->site()` or `page()` instead. If only because those are available in more contexts.

  • Flo

    @fvsch @getkirby That‘s a very good point I didn’t had in mind! Thanks for your reply.

  • Florens Verschelde

    @flokosiol @getkirby I have a custom DefaultPage model that all page classes inherit from. I just added a `field` function as a shortcut:

    ```php
    class DefaultPage extends Page
    {
    public function field(string $key): Field {
    return $this->content()->get($key);
    }
    }
    ```

    Versus the alternatives:

    - `$page->field_name()` has unknown type
    - `$page->content()->field_name()` has unknown type
    - `$page->content()->get('field_name')` returns `Field|array` because if you don't provide a field name you get an array of all fields (equivalent to `$page->content()->fields()`), and that's too ambiguous for PHP's type system (TypeScript could type it correctly, maybe Psalm too, but built-in PHP8 types can't).

    Limitations:

    - You have to setup your DefaultPage class, require it, create custom model classes for every page type. I already do it, but it's busywork.
    - It's good that now PHP knows that you get a `Kirby\Content\Field`, but that class type is not super useful because most of the utility Field methods are not statistically defined, they're injected as default config in github.com/getkirby/kirby/blob

  • nilsmielke ⁂

    @flokosiol @getkirby Interesting approach. Will try and see, what “feels” better.

  • Luke Dorny

    @nilsmielke @flokosiol @getkirby yes! This was a Kirby concept I feel like I bumped into from time to time when I would use page methods that I thought were my own. The content clarifier always seemed unnecessary, but your article clears up for me me understanding of it. Thanks!
    Also, excitingly, v5 shares the site controller site wide! Love this.

  • Flo

    @Luke @nilsmielke @getkirby Thanks for your replies, both of you. Much appreciated!

  • Richard the Brave 🇨🇦

    @flokosiol @getkirby Really enjoying your posts lately!

  • Flo

    @richardthebrave @getkirby Thanks a lot for your kind feedback. That‘s wonderful to hear! 😊

  • Luke Dorny

    @flokosiol oh, my goodness, very clever. At times I realized if only fleetingly that I was using a shortcut for content() but not in time to face object collisions with no clear way to resolve the issues. I really appreciate articles like this. Thank you. @getkirby

  • Luke Dorny

    @flokosiol @getkirby is that the right term for this? Object collisions? I don’t even know.

  • Flo

    @Luke @getkirby I don’t know, tbh. Unfortunately, I don't have the theoretical background to answer this question. 🤷‍♂️

  • Luke Dorny

    @flokosiol No problem. I'm anxiously engaged in improving my understanding of programming, but it's slow-going for me. :)

  • Flo

    @Luke It‘s not about the speed, it’s about the progress and the understanding. So keep learning! It’s what we all do. 🙃

Latest

Use your fucking brain.

Featured

It‘s the rests what makes the groove!

Matthias Ott recently published a blog post which really resonates with me. Starting from a musical point of view, he wrote about making space. This is my reply (or addition).

pageview counter pixel