◆ やっぱり古い感じがする
◆ テンプレートの書き方自体は良いんだけど……
  ◆ PHP からの使い方や出力されるコードやドキュメントの充実度や開発の活発度とかが
◆ 変数展開は 「``」

前の Composer 使ってみたのときに依存パッケージがなくて 名前がタイプしやすいというだけで Smarty を入れました
composer をちゃんと使ってみる
composer をちゃんと使ってみる2

せっかく入れたのに全く触れないのももったいないかな と思って使ってみました

Smarty

PHP として Smarty のインスタンスを作ったり操作することはありませんでしたが Smarty のテンプレート自体は書いたことがあります
よくある 「{{}}」 でなく 「{}」 だけなのでシンプルで書きやすいです
また 「|」 で変数にパイプで関数を適用できる機能があったりとテンプレートだけで見るなら最近のと比べてもけっこう書きやすいものです

ただ 出力されるファイルは読む気もしないようなことになっていますし ドキュメントは古くて読みづらいです
更新はほとんどなくて 改善があまり期待できません
また 独特な構文な分 独自のパーサで行ってるらしく それもドキュメントがいまいちで これでできるの?と思うことも少なくありません
一見できそうなのにできなかったということもあります

実行する

とりあえず PHP からテンプレートを HTML に変換してみます

[app.php]
<?php

require __DIR__ . '/vendor/autoload.php';

$s = new Smarty();

$tpl_str = '
<!doctype html>
<table>
<tr><th>a</th><td>{$a}</td></tr>
<tr><th>x</th><td>{$x}</td></tr>
</table>
';

$s->assign('a', 'b');
$s->assign('x', 'y');
$s->display("string:{$tpl_str}");

[user@fedora]/mnt/win/test/dir000/ctes% php app.php
<!doctype html>
<table>
<tr><th>a</th><td>b</td></tr>
<tr><th>x</th><td>y</td></tr>
</table>

ファイルじゃなくて文字列からなら ファイル名のところに 「string:」 から始まる文字列にするとか テンプレート変数は別にアサインしないといけないとか なんか最近のテンプレートエンジンの感じとは違います

生成された PHP ファイルはこうなっていました

<?php
/* Smarty version 3.1.32, created on 2018-05-23 06:50:35
from '1f2e37f0a6f3348d65c0028d0d5d58257d931034' */

/* @var Smarty_Internal_Template $_smarty_tpl */
if ($_smarty_tpl->_decodeProperties($_smarty_tpl, array (
'version' => '3.1.32',
'unifunc' => 'content_5b050f3bbce570_17539451',
'has_nocache_code' => false,
'file_dependency' =>
array (
),
'includes' =>
array (
),
),false)) {
function content_5b050f3bbce570_17539451 (Smarty_Internal_Template $_smarty_tpl) {
?>
<!doctype html>
<table>
<tr><th>a</th><td><?php echo $_smarty_tpl->tpl_vars['a']->value;?>
</td></tr>
<tr><th>x</th><td><?php echo $_smarty_tpl->tpl_vars['x']->value;?>
</td></tr>
</table>
<?php }
}

たしか Blade はもっときれいだった気がします

そういう感じで Smarty はあんまり使う気が出ません

変数展開

適当に色々試したり JavaScript でのテンプレートエンジンで書いてたものを Smarty 版にしてみたりとしていたら 変数展開で困りました
PHP でいう変数展開をして 文字列の前後に文字列を追加した文字列を別の変数に代入したいです
PHP と同じようにやってる例をよく見ましたが 「``」 を使うと書いてるところもありました
どっちも行けるんだと思ってましたが escape_html が有効なら 「``」 じゃないと二重エスケープされるケースがあります

<?php

require __DIR__ . '/vendor/autoload.php';

$s = new Smarty();
$s->escape_html = true;

$tpl_str = '
{$empty=""}
{$alternative="<p>text</p>"}
{$text1=$alternative}
{$text2="{$alternative}"}
{$text3="prefix {$empty|default:$alternative} suffix"}
{$text4="prefix `$empty|default:$alternative` suffix"}
{$text1}
{$text2}
{$text3}
{$text4}
';

$s->display("string:{$tpl_str}");
&lt;p&gt;text&lt;/p&gt;
&lt;p&gt;text&lt;/p&gt;
prefix &amp;lt;p&amp;gt;text&amp;lt;/p&amp;gt; suffix
prefix &lt;p&gt;text&lt;/p&gt; suffix

text3 だけが二重エスケープされています
ソースを見てみると

$_smarty_tpl->_assignInScope('empty', '');
$_smarty_tpl->_assignInScope('alternative', "<p>text</p>");
$_smarty_tpl->_assignInScope('text1', $_smarty_tpl->tpl_vars['alternative']->value);
$_smarty_tpl->_assignInScope('text2', ((string)$_smarty_tpl->tpl_vars['alternative']->value));
ob_start();
echo htmlspecialchars((($tmp = @$_smarty_tpl->tpl_vars['empty']->value)===null||$tmp==='' ? $_smarty_tpl->tpl_vars['alternative']->value : $tmp), ENT_QUOTES, 'UTF-8');
$_prefixVariable1=ob_get_clean();
$_smarty_tpl->_assignInScope('text3', "prefix ".$_prefixVariable1." suffix");
$_smarty_tpl->_assignInScope('text4', "prefix ".((string)((($tmp = @$_smarty_tpl->tpl_vars['empty']->value)===null||$tmp==='' ? $_smarty_tpl->tpl_vars['alternative']->value : $tmp)))." suffix");
echo htmlspecialchars($_smarty_tpl->tpl_vars['text1']->value, ENT_QUOTES, 'UTF-8');?>

<?php echo htmlspecialchars($_smarty_tpl->tpl_vars['text2']->value, ENT_QUOTES, 'UTF-8');?>

<?php echo htmlspecialchars($_smarty_tpl->tpl_vars['text3']->value, ENT_QUOTES, 'UTF-8');?>

<?php echo htmlspecialchars($_smarty_tpl->tpl_vars['text4']->value, ENT_QUOTES, 'UTF-8');?>

となっていました

text3 だけが ob_start を使って実際に出力してその文字列を変数に代入しています
実際の出力が起きるので escape_html が有効だと htmlspecialchars 関数に通されてエスケープされます
その変数を出力するときにもまたエスケープされるのでエスケープされる文字が入っていた場合には画面に HTML エスケープされた文字列が表示されてしまいます

text2 はエスケープされていないので 「{}」 での変数展開でもプレフィックスやサフィックス部分がない実質代入と同じ処理だと何も起きないようです
text4 もエスケープされていないので 「``」 にしておけば大丈夫みたいです

よくわからないですね……

こういうなんでこうなるの?と思う箇所がいっぱいあるのが Smarty なんですよね
一応タグの書きやすさと依存なしで Smarty のパッケージだけで使えるのは 良いところなんですけどね