DEV Community

Oliver Davies
Oliver Davies

Posted on • Originally published at oliverdavies.uk on

Don't put business logic in templates

Here is some code from my website:

{% set talkCount = 0 %}

{% for talk in data.talks %}
  {% for event in talk.events if 'today'|date('U') >= event.date|date('U') %}
    {% set talkCount = talkCount + 1 %}
  {% endfor %}
{% endfor %}
Enter fullscreen mode Exit fullscreen mode

It is business logic responsible for counting the number of talks I've given at different events so I can display it on my Talks page.

It starts at zero, loops over each talk, and increments the talk count if the event is the current day or a past date.

It's only used in a single place, so the same logic isn't duplicated elsewhere.

But it's in the page's Twig template.

It has no test coverage.

If I need to change or refactor it, I'd need to test it again manually.

Don't do this.

So, what should I do?

It's OK to put simple presentational logic, such as looping over a list or whether to show or hide a value within a template, but not complex business logic.

Business logic should be separated and executed elsewhere. The values should be passed to the template to be rendered.

This makes the business logic easier to test as you can test the logic itself and determine the value passed to the template is correct without being concerned about the templating engine.

In an application, you may need to output a value to a template and a terminal. You'd have one source of truth, such as a Service, Action or Command class that calculates the value before passing it to the appropriate output.

Once the logic is separated, you only need to test it once.

Here's the thing

In a previous version of my website, I did this by creating a custom Twig function.

It was as simple as adding `` to the template.

All the logic was moved from the template to my custom extension.

The logic was separated.

It had tests.

This is the approach I'd take to achieve the same result for a client application.

For a client, I want to run a test suite and be confident my logic works as expected - now and in the future.

For myself, and for calculating something simple, this is fine.

P.S. If you're creating a new Drupal module, try my free Drupal module template.

Top comments (0)