Best Practices

Learn the four most common Tplix mistakes and how to fix them: avoid embedded PHP, assign flags not objects, keep SQL out of templates, and use plugins for business logic.

Best Practices

Tplix makes it easier to separate business logic from presentation — but it doesn't guarantee it. Like any tool, it requires thoughtful use. These are the most common pitfalls developers run into, and how to avoid them.

A note on roles

In these examples we treat the PHP developer and the template designer as separate people — even if it's the same person in your team. This mental model helps clarify what belongs in PHP and what belongs in templates. When in doubt, ask: "Is this presentation, or application logic?"

1

Do not embed PHP in templates

The {php} tag was originally provided as a last resort. Experience showed it creates more problems than it solves — it is now deprecated. Despite this, developers reach for it as the quick fix. It is always the wrong call.

The correct approach: implement a plugin and keep all PHP logic outside the template.

Say we have a PHP function that fetches a weather forecast and returns HTML markup:

PHP — existing function
function get_forecast($zipcode) { // some weather class we use to do the fetching include_once('weather.php'); // get the forecast from the weather station $forecast = Weather::forecast($zipcode); // mark up and return $output = "<table>"; $output .= "<tr><td>Temp:</td><td>".$forecast['temp']."</td></tr>"; $output .= "</table>"; return $output; }
✕ The wrong way — using {php} tags
template.tpl — bad: embedded PHP
{* this is a comment *} {php}echo get_forecast($zipcode);{/php}
Problem: $zipcode is a template variable — it won't work inside a {php} block. So you patch it:
template.tpl — still bad: accessing Tplix internals
{php}echo get_forecast($this->getTemplateVars('zipcode'));{/php}
Problem: get_forecast() isn't loaded. So you add an include:
template.tpl — now a full mess
{php} include(dirname(MY_APP).DIRECTORY_SEPARATOR.'forecast.php'); echo get_forecast($this->getTemplateVars('zipcode')); {/php}
What went wrong
  • Business logic (file includes, class calls) is now inside the template
  • If the designer wants to change the markup, they have to dig into PHP code
  • The separation that Tplix was designed to create has been completely defeated
✓ The right way — a clean plugin
function.get_forecast.php — plugin
<?php /* * Tplix plugin * File: function.get_forecast.php * Type: function * Name: get_forecast * Purpose: gets the weather forecast */ function tplix_function_get_forecast($params, $tplix) { include_once('weather.php'); $forecast = Weather::forecast($params['zipcode']); // assign data to the template var, not markup $tplix->assign($params['assign'], $forecast); } ?>
template.tpl — clean, readable
{get_forecast zipcode=$zipcode assign="forecast"} <div class="forecast">Temp: {$forecast.temp}</div>
Even simpler alternative — if you don't need the plugin to be callable from any template independently, just assign from PHP before rendering:
PHP
$tplix->assign('forecast', get_forecast($zipcode));
Tplix
<div class="forecast">Temp: {$forecast.temp}</div>
2

Keep PHP constructs separate

Assigning a whole PHP object to a template and calling its methods inside the template creates tight coupling between your PHP code and your presentation. Changes to the object structure break templates — and template designers are exposed to internals they shouldn't need to know about.

✕ Assigning a PHP object directly to the template
PHP
if($roles->isEditor($_SESSION['user_id'])) { /* do something */ }
template.tpl — bad: calling PHP object methods in template
{if $roles->isEditor($tplix.session.user_id)} ... show edit buttons here ... {/if}
  • Tight coupling — changing the $roles class breaks the template
  • Application logic (user roles) has leaked into the presentation layer
  • The designer is forced to understand user role systems — completely unnecessary
✓ Assign a simple boolean flag — the right way
PHP — resolve the logic here
// assign a simple flag — the template doesn't need to know how it was decided $tplix->assign('show_edit_buttons', $roles->isEditor($_SESSION['user_id']));
template.tpl — focused purely on presentation
{if $show_edit_buttons} ... show edit buttons here ... {/if}
The template now has zero knowledge of user roles, sessions, or PHP objects. It only knows one thing: should I show the buttons or not? That is pure presentation logic.
3

Keep business logic separate

It is tempting to write clever template functions that do "neat things" — but business logic does not belong in a template function, even if it's wrapped in a Tplix tag. A direct SQL query in a template is a classic example of a rule violation.

✕ SQL in a template tag — never do this
template.tpl — bad: raw SQL in template
{sql statement="select * from categories order by catname limit=$start,$limit" assign="result"} {$result.catname} {/sql}
  • SQL statements are business logic — the designer should never know where content comes from
  • Opens a serious SQL injection security risk if template parameters come from user input
  • A designer typo could silently break or expose database queries
✓ A purpose-built plugin that hides the SQL entirely
template.tpl — SQL is completely hidden
{get_categories limit=10 assign="result"} {$result.catname} {/get_categories}

The get_categories plugin handles parameter sanitisation and the database query internally. The template only deals with displaying the result.

4

How to identify business vs presentation logic

The line isn't always obvious. A useful test: does this logic have anything to do with how content is displayed? If not, it belongs in PHP. If you find template syntax becoming complicated or terse, that's a signal that logic has crept in where it shouldn't be.

✕ Regex modifier directly in template — business logic disguised as presentation
template.tpl — bad: complex regex in template
{$description|regex_replace:"!(\w+@\w+)!":'<a href="mailto:$1">$1</a>'}
Terse, cryptic syntax is a dead giveaway. A designer maintaining this template has no idea what !(\w+@\w+)! means — or what breaks if they accidentally edit it.
✓ Wrap it in a named modifier plugin
modifier.link_emails.php — regex lives here
<?php /* * Tplix plugin * File: modifier.link_emails.php * Type: modifier * Name: link_emails * Purpose: converts plain emails in text into HTML mailto links */ function tplix_modifier_link_emails($string) { return preg_replace( '!(\w+@\w+)!', '<a href="mailto:$1">$1</a>', $string ); } ?>
template.tpl — self-explanatory
{$description|link_emails}
Anyone reading this template — including a designer with zero PHP knowledge — immediately understands what link_emails does. The regex implementation is safely hidden in PHP where it belongs.

Quick decision guide

?
Does this deal with how data is fetched or transformed?
Database queries, regex, API calls, role checks → belongs in PHP
?
Is the template syntax getting complicated or hard to read?
That's a signal logic has crept in. Wrap it in a plugin or assign from PHP first.
?
Could a non-developer understand and edit this template safely?
If not, the template has too much logic. Simplify until the answer is yes.
?
Does this deal purely with layout, display, or formatting?
Loops over data, conditionally showing elements, formatting output → belongs in template
🚫
No {php} tags
🔒
Assign flags, not objects
🗄️
SQL stays in PHP
🔌
Use plugins for logic
Build better templates from the start

Follow these practices and your templates will stay clean, maintainable, and designer-friendly at any scale.

Read the Docs →