使用したバージョンはSmarty3.1.27、twig1.20.0。
<?php
$data = [
'text'=>'<b>あ</b>',
'text2'=>"abc\n\ndefg",
'arr' =>[
['href'=>'link1'],
'key'=>['href'=>'link2'],
],
'int' => 1,
'hoge' => null,
'obj' => (object)['key'=>'value'],
'select' => range(date('Y'), date('Y')+10),
];
// Twig
require_once('path/to/twig/Autoloader.php');
Twig_Autoloader::register();
$twig = new Twig_Environment(new Twig_Loader_Filesystem('./'), ['debug' => true]);
$twig->addExtension(new Twig_Extension_Debug());
echo $twig->render('twig_template.html', $data);
// Smarty
require_once('path/to/smarty/Smarty.class.php');
$smarty = new Smarty();
$smarty->assign($data);
$smarty->display('smarty_template.html');
twig_template.html
{% extends 'twig_parent.html' %}
{% block body %}
<h2>値を表示する</h2>
{{ text }}
{{ text|raw }}
{{ obj.key }}
<h2>修正子</h2>
{{ text2|nl2br|upper|slice(0,10) }}
{{ date().format('Y-m-d H:i:s') }}
<h2>繰り返し</h2>
{% for k, v in arr %}
<a href="{{ v.href }}">{{ k }}</a><br />
{% if loop.last %}ループの最後{% endif %}
{% endfor %}
{% for v in 1..10 %} {{ v }} {% endfor %} ..でrange
<h2>継承</h2>
{% include 'twig_include.html' with {'var1':'val1'} %}
<h2>条件分岐</h2>
{% if int == true %} ===は「X is same as(Y)」と書かないといけない。 {% endif %}
{{ 6 is divisible by(3) }} 3で割り切れるか。
{{ 5 is odd }} 奇数か。
{{ hoge is empty }} 未定義か。falseはtrue、0はfalseになるのでPHPのemptyとは違うようだ。
{{ hoge is defined }} emptyの逆ではない。nullでも何でも存在さえしていればtrue。
{{ [] is iterable }} Traversableもしくは配列。
<h2>定義済</h2>
{{ constant('PHP_VERSION') }}
スーパーグローバルにはアクセスできない?
<h2>フォーム</h2>
<input type="text" name="name" value="{{ text|e }}"/>
<select name="year">
{% for year in select %}
<option value="{{ year|e }}">{{ year|e }}</option>
{% endfor %}
</select>年
<h2>関数</h2>
{% macro func1(arg) %}{{ dump(arg) }} {% endmacro %}
{% import _self as dummy %}
{{ dummy.func1([1,2,3]) }}
dumpを使うにはTwig_Environmentにdebug=true、Twig_Extension_DebugをaddExtensionの2手順が必要。
同一ファイル内のmacroを使うには_selfをimportしないといけない。
<h2>構造</h2>
{# コメントアウト {{ {% {# #}
{% verbatim %}構文解析をパス {{ {% {# {% endverbatim %}
{% endblock %}
twig_parent.html
<html>
<body>
{% block body %}テンプレ継承{% endblock %}
</body>
</html>
twig_include.html
インクルード {{ var1 }}
smarty_template.html
{extends file='smarty_parent.html'}
{block name=body}
<h2>値を表示する</h2>
{$text|escape}
{$text}
{$obj->key}
<h2>修正子</h2>
{$text2|nl2br|upper|truncate:10:'':true}
{$smarty.now|date_format:'Y-m-d H:i:s' }
<h2>繰り返し</h2>
{foreach $arr as $v}
<a href="{$v.href|escape}">{$v@key|escape}</a><br />
{if $v@last}ループの最後{/if}
{/foreach}
<h2>継承</h2>
{include file='smarty_include.html' var1='val1'}
<h2>条件分岐</h2>
{if $int == true } ===はそのまま書ける。 {/if}
{6 is div by 3} 3で割り切れるか。
{5 is not div by 2} 奇数か。
{$hoge|defined} 実は全てのPHP関数を修正子として呼べる。
{$hoge|default:false} emptyは言語構造なので修正子として呼べない。
{[]|is_a:'Traversable'} Traversableか。
<h2>定義済</h2>
{$smarty.const.PHP_VERSION}
{$smarty.session.hoge|escape|default:''}
<h2>フォーム</h2>
<input type="text" name="name" value="{$text|escape}"/>
<select name="year">
{html_options options=$select }
</select>年
<h2>関数</h2>
{function name=func1} {$arg|var_dump} {/function}
{call name=func1 arg=[1]}
<h2>構造</h2>
{* コメントアウト { {* *}
{literal}構文解析をパス { {* {/literal}
{/block}
smarty_parent.html
<html>
<body>
{block name=body}テンプレ継承{/block}
</body>
</html>
smarty_include.html
インクルード {$var1|escape}
無設定時の初期値はSmartyがエスケープ無し、Twigはエスケープ有りですが、
そのあたりは設定で変えられるので特に優劣には関係しないでしょう。
マニュアルは圧倒的にSmartyの勝利。
なにせ日本語があるからね。
どっちがいいか?どっちを選ぶべきか?
どっちでもいいんじゃない。
テンプレートエンジンでやりたいようなことは、どちらを使ってもだいたいできるので、好きな方を選べばいいと思うよ。
私としては、Twigを使い慣れてないからということもありますが、Smartyのほうが楽という感想です。
今時defineとかrequire_once山盛りでソースは古臭いし、修正子はfunctionべた書きでグローバル汚染するしと残念な感じだけど、使うぶんにはあんまり関係ないしね。
え?レスポンスが遅い?
そんなシビアなサイトにPHPなんて使ってるんじゃない。