Separate logic (.php) from presentation (.stpl) with a
tiny, single-file engine that speaks the Smarty syntax you already know.
composer require sluz/sluz
include 'sluz.class.php';
$s = new sluz();
$s->assign('name', 'Jason');
$s->assign('languages', ['PHP', 'Perl', 'JS']);
print $s->fetch('tpls/script.stpl');
<h1>Hello {$name|default:"world"}</h1>
<ul>
{foreach $languages as $item}
<li>{$item|strtoupper}</li>
{/foreach}
</ul>
Drop in one file, and get familiar Smarty-like syntax, modifier chaining, and layout tools — with zero bloat and zero surprises.
Just sluz.class.php. No autoloader maze, no build step. Simple. Copy it and go.
Requires PHP 8.x+ and nothing else. Composer-friendly but not Composer-required.
If you know Smarty, you know Sluz. Variables, blocks, and filters feel like home.
{$var|default:"?"|strtoupper} — pipe as many native PHP functions as you like.
{$user.name.first} → $user['name']['first']. Arrays stay ergonomic.
{$x + 3}, {count($arr)} and friends — math and function calls right in templates.
$__FOREACH_FIRST, $__FOREACH_LAST, $__FOREACH_INDEX for clean list rendering.
{include} and parent/child templates for composable pages.
{literal} & {* comments *}set_delimiters('[', ']')A tiny vocabulary that covers the 95% you actually use.
| Syntax | Example | Output |
|---|---|---|
{$var} | {$name} | Jason |
{$hash.key} / {$arr.0} | {$cust.first} | Scott |
{$var|modifier} | {$animal|strtoupper} | KITTEN |
{$var|mod:params} | {$greet|substr:0,3} | Hel |
{$var|mod1|mod2} | {$word|strtolower|ucfirst} | Crazy |
{$var|default:"val"} | {$null|default:"?"} | ? |
{$var|escape} | {$name|escape} | <script> → <script> |
{$expr} | {$number + 3} | 18 |
{if}…{elseif}…{else}{/if} | {if $x}yes{else}no{/if} | yes |
{foreach $a as $v} | {foreach $items as $x}{$x}{/foreach} | onetwothree |
{foreach $a as $k => $v} | {foreach $m as $k => $v}{$k}{/foreach} | 012 |
$__FOREACH_FIRST/_LAST/_INDEX | {if $__FOREACH_FIRST}…{/if} | — |
{include file='…'} | {include file='header.stpl'} | — |
{literal}…{/literal} | {literal}function foo() { {/literal} | function foo() { |
{* comment *} | {* hidden *} | (empty) |
{function()} | {count($array)} | 3 |
Composer or single-file drop-in — you choose.
# via Composer
composer require sluz/sluz
# or just grab the one file you need
curl -O https://www.sluz.org/latest/sluz.class.php
Save as tpls/hello.stpl next to your script.
<h1>Hello {$name}!</h1>
{if $items}
<ul>
{foreach $items as $item}
<li>{$item}</li>
{/foreach}
</ul>
{/if}
Assign data and fetch. That's it.
<?php
require 'sluz.class.php';
$s = new sluz();
$s->assign('name', 'Ada');
$s->assign(['items' => ['Logic','Presentation']]);
print $s->fetch('tpls/hello.stpl');
Classic, simple, or inline — same engine, three ergonomics.
Full control: assign, fetch, parent templates.
$s = new sluz();
$s->assign('age', 38);
print $s->fetch('tpls/index.stpl');
Singleton helper — auto-renders tpls/[script].stpl in the destructor.
sluz('name', 'Ada'); // Alias for assign()
sluz('color', 'green');
// done — template renders itself
Template lives in the same file after __halt_compiler();. Great for single file scripts.
$s->fetch(SLUZ_INLINE);
__halt_compiler();
<h1>Hello {$name}</h1>
Variables are verbatim by default. Wrap untrusted output with |escape, or flip the safety switch and auto-escape everything.
{$var|escape} — htmlspecialchars{$var|escape:"url"} / |escape:"js" for URL and JS contexts$s->setEscapeHtml(true) + |raw to opt out when HTML is trusted{* manual escaping *}
{$user_input|escape} {* HTML-encode *}
{$redirect_url|escape:"url"} {* URL-encode *}
{$inline_js|escape:"js"} {* JSON-encode for JS *}
{* auto-escape mode (PHP) *}
$s->setEscapeHtml(true);
{$user_input} {* now auto-escaped *}
{$user_input|escape} {* not double-escaped *}
{$trusted_html|raw} {* opt out — verbatim *}
{$var} blocks only. Expression blocks like {$x + 3} and function calls like {count($arr)} are not auto-escaped.
Mirrors the bits of Smarty you actually reach for.
$s->assign('key', 'value')single or bulk ['k'=>'v']$s->fetch('tpls/a.stpl')render template file to string$s->display('tpls/b.stpl')print rendered templatephp unit_tests/tests.php # full suite
php unit_tests/tests.php "Foreach" # filter by name
php unit_tests/tests.php --simple # quiet counts only
Sluz started in PHP, but the same light Smarty spirit lives on in Perl and JavaScript.
One file to include, Smarty-like syntax to love, and no hidden magic. Grab Sluz and keep presentation where it belongs.
composer require sluz/sluz — your call.