こんにちは。先日入社しましたmiyakeと申します。新入りです。
今日はSmartyでRuby on Rails的なレイアウトテンプレート機能を実現するTipsをご紹介します。
まず、そもそもRailsのレイアウトテンプレートとはどんな物なのか、簡単に解説します。
Smartyに限らず、何らかのテンプレートエンジンでページを出力する場合、ヘッダやフッタといった共通部分を別ファイルに切り分けるというのはよくあるアプローチです。
この場合、そのページのテンプレートファイルに加えて、ヘッダとフッタのテンプレートを別途用意します。
これに対して、レイアウトテンプレートはそのページのテンプレートと「土台になるテンプレート(=レイアウトテンプレート)」でページを出力します。
実際のHTMLに照らし合わせて図にすると、こんなイメージです。
レイアウトテンプレートのイメージ posted by (C)フォト蔵
ヘッダ・フッタを分割した場合、各テンプレートはHTMLの一部分を切り出した内容になります。
一方レイアウトを使用すると、レイアウトテンプレートはHTMLとして成立する形で記述できます。デザイナーさんにテンプレートを作ってもらう時も、コーディング後にファイルを分割する作業がなくて済むので効率的です。
後から修正が入った場合も、レイアウトは1枚のHTMLとして成立しているので作業が楽ですし、レイアウトテンプレートをバリデータにかけることもできるのでトラブルを回避しやすくなります。
実際のテンプレートは以下のように記述します。
layout.tpl
<html>
<head>
<title>{$TITLE}</title>
</head>
<body>{$CONTENT}</body>
</html>
content.tpl
{assign var="TITLE" value="レイアウトテンプレートのサンプル"}
<h1>レイアウトテンプレート</h1>
<p>こいつが各ページのテンプレートになります。</p>
ページのテンプレート(僕はコンテンツテンプレートと呼んでいます)はHTMLの一部分だけになってしまいますが、レイアウトテンプレートは1枚のHTMLとして成立します(サンプルは必要な要素も大幅に省略していますが)。
ページを出力する時は、layout.tplの{$CONTENT}にcontent.tplの内容が展開されるようにします。
また、コンテンツテンプレート側で宣言したテンプレート変数が、レイアウトから参照できるようにします。ページのタイトルや個別に読み込むCSS、JavaScriptなどを変数とすることで柔軟性のあるレイアウトが作れます。
php側の処理は非常に簡単です。ここでは、レイアウト処理の部分だけ掲載します。
$content = $smarty->fetch('content.tpl');
$smarty->assign('CONTENT', $content);
$smarty->display('layout.tpl');
通常、Smartyではテンプレートを上の行から順に処理するので、変数は宣言した行以降でしか有効になりません。が、このようにcontent.tplを先にfetchしてやると、fetchした時点でcontent.tplの変数定義が全て処理されるため、layout.tplではcontent.tpl内で定義した全ての変数が有効になります。
分かってしまえば非常に単純な仕組みですが、なかなか使えるんじゃないでしょうか。
手元のライブラリでは、このアプローチをベースに
- 表示するページのディレクトリからlayout.tplを探す
- 同じディレクトリにない場合は親ディレクトリを再帰的にたどって探す
- コンテンツ側でテンプレート変数{$LAYOUT}が指定されたらそのファイルをレイアウトとする
- {$LAYOUT}が予約語「plain」だったらレイアウトは適用しない
といった機能を追加しています。皆さんも、自分なりの機能を追加したSmartyで快適なテンプレートライフを模索してみてはいかがでしょうか?
最後に。レイアウトテンプレートにSmartyキャッシュを使用する場合の注意点を。
コンテンツのキャッシュが更新された時には、レイアウトのキャッシュを手動でクリアしてください。レイアウトは自分自身に変更がない限りは有効時間までキャッシュを更新してくまれせんので。