- Smarty
- Twig
- etc...
- テンプレートエンジン特有の構文を覚えなければならない
- IDE がシンタックスハイライトなどに対応していないことがある
<h1>Users</h1>
<ul>
{foreach from=$users item=user}
<li>{$user.username}</li>
{/foreach}
</ul><h1>Users</h1>
<ul>
{% for user in users %}
<li>{{ user.username }}</li>
{% endfor %}
</ul>- テンプレートエンジン特有の構文を覚える必要がない
- たいていの IDE がシンタックスハイライトなどに対応している
<h1>Users</h1>
<ul>
<?php foreach ($users as $user): ?>
<li><?= $user['username'] ?></li>
<?php endforeach; ?>
</ul>とか
<h1>Users</h1>
<ul>
<?php foreach ($users as $user) { ?>
<li><?= $user['username'] ?></li>
<?php } ?>
</ul>PHP とまったく同じ
↓
テンプレートエンジン特有の構文を覚える必要がない
- ハイライトどころかアウトライン解析までできている
- もちろん Eclipse にも対応
- とうぜん NetBeans にも対応 使ったこと無いけど
むしろ対応していないなら PHP の IDE を名乗るべきではない
IDE が対応するのではない、対応しているものが IDE なのだ
テンプレートにアサインする変数がオブジェクトなら
ちょっとしたおまじないで入力補完にまで対応
<?php /* @var $users User[] */ ?>
<h1>Users</h1>
<ul>
<?php foreach ($users as $user): ?>
<li><?= $user->getUsername() ?></li>
<?php endforeach; ?>
</ul>このステキなテンプレートエンジンの名前は
素の PHP がテンプレートとして使われることは多い
- Zend Framework
- CakePHP
- FuelPHP
- etc...
例えばこんなの
index.php
<?php
$name = filter_input(INPUT_GET, 'name');
include __DIR__ . '/index.html.php';index.html.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
< body>
Hello <?= $name ?>
< /body>
</html>ここ、いわゆる XSS です
Hello <?= $name ?>エスケープが必要
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
< body>
Hello <?= htmlspecialchars($name, ENT_QUOTES) ?>
</ body>
</html>さすがに毎度こんなのを書いてたらめんどくさくて死ぬ
<?= htmlspecialchars($name, ENT_QUOTES) ?>のでフレームワークによって別の書き方が提供されています
<?= $this->escapeHtml($name) ?>- ビューヘルパーと呼ばれるもの
- あんまり楽になった気がしない
<?= h($name) ?>hというグローバル関数が定義されているbasics.phpを見ると他にもいろいろ定義されている
<?= $name ?>- あらかじめエスケープされた変数がアサインされる
- ただしオブジェクトをアサインするときに困りそう
- Smarty2 の自動エスケープはクソ
- 出力時ではなく参照時にエスケープされるから
- Smarty3 なら良い感じに自動でエスケープしてくれる
- Twig も自動でエスケープしてくれる
...
素の PHP でも同じことがしたい
index.php
<?php
require __DIR__ . '/../vendor/autoload.php';
use PhpRenderer\Renderer;
$data = array(
'name' => "<script>alert('!!!')< /script>",
'html' => "<strong>oreore</strong>",
);
echo (new Renderer)->render(__DIR__ . '/index.html.php', $data);index.html.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
< body>
Hello <?= $name ?>.
<br>
None Escape <?php echo $html ?>
< /body>
</html><?= $name ?>のようなショートタグ- 自動エスケープ
<?php echo $html ?>のような普通の PHP タグ- エスケープなし
- StreamWrapper
- Tokenizer
<?php
stream_wrapper_register('oreore', 'OreOreClass');oreore:path/to/file
のようなストリームラッパーが使えるようになります。
OreOreClass には "path/to/file" が渡されるので、
そのファイルを開いて独自の処理ができます。
$tokens = token_get_all($source);開いたファイルを PHP のソースコードとして、
トークン(字句)に分割します。
<?= → T_OPEN_TAG_WITH_ECHO
?> → T_CLOSE_TAGこの2つのトークンを見つけて、
<?= ... ?>を、
<?=func( ... )?>のように置換します。
include 'oreore://index.html.php'のようにインクルードすると、
<?= ... ?>を置換したソースコードがインクルードされます。
index.html.phpには OPCache は効かないfile:とphar:しか対応しないようにハードコードされてる- 置換後の opcode がキャッシュされると思ってた・・・
index.html.phpにブレークポイントを仕込んでも無駄- デバッガが止まりません



