肉とビールとパンケーキ by @sotarok

少し大人になった「肉とご飯と甘いもの」

Smarty入門者のための逆引きSmartyリファレンス


なんかSmarty入門記事がはやっているようなので書いた。


Smartyの構文(関数)、修飾子、カスタム関数の中から、よく使うもの・最悪これだけ知ってれば大体かけるよ、というものをピックアップしました。
これ以外にもたくさんの関数や修飾子がありますので、知りたい方はマニュアルをあさってみると良いです。

まあマニュアルを見れば大体わかることですが、逆引きがあると便利っちゃあ便利・・・ですか?便利ですよね?(ぉ
つーか最初のほうなんてまんまマニュアル見ればよいことですが。。。まあいっか。

目次

はじめに(Smartyを使うために)

  • Smartyの設定
    • Smartyの設置
    • 必要なディレクトリ
  • Smartyを使うためのPHPファイルの記述
    • 最低限必要なこと
    • PHPからテンプレートに表示する変数を代入する
    • テンプレートを指定して出力する


Smartyテンプレート側逆引きリファレンス(テンプレートデザイナのための Smarty)

  • 変数
    • テンプレートでPHPで設定された変数を表示する
  • 構文(組み込み関数)
    • コメントアウトする
    • デリミタを無視してそのまま表示する
    • 条件で分岐する(if)
    • 配列をすべてループする
    • 別のテンプレートを埋め込む
  • 修飾子
    • 修飾子の使い方
    • 出力する変数のエスケープ処理をする
    • 日付の表示方法を変更する
    • 文字列を置換する
    • 改行をbrタグに変換する
    • 変数が空だった場合のデフォルトの出力を設定する
  • HTMLヘルパー(カスタム関数)
    • 循環して出力する(テーブルの行の色を交互に変えたりする)
    • ラジオボタンを設定する
    • セレクトボックスを設定する
    • チェックボックスを設定する


PHP側逆引きリファレンス

  • 気が向いたら書く

はじめに(Smartyを使うために)

Smartyの設定

Smartyの設置

Smartyを使うというなら、まずSmartyを設置しなければいけません。最初だけ設定がちょっと面倒ですが、一度やってしまえば簡単です。
まず、Smarty本家からダウンロードしてきましょう。ダウンロードをすると

  • demo
  • libs
  • misc
  • unit_test

...

のようにファイルが現れます。この、「libs」というディレクトリの中にSmarty本体が入っています。まず、これをどこかに移し、ディレクトリ名を「libs」→「Smarty」と変更しておきます。

必要なディレクトリ

次に、ディレクトリを設定します。
基本的には、

  • テンプレートを置くディレクトリ
  • コンパイル済みのテンプレートが置かれるディレクトリ(深く考えなくてOK)

の2つを作成すればOKです。

この2つは、できればウェブ上からアクセスできない位置に置いてください(http://... 経由でアクセスできない場所)。レンタルサーバなどでそれができない場合は、.htaccessなどでそのディレクトリへのアクセスを禁止しておきます。

.htaccessの記述例

order deny,allow
deny from all

今回は、この2つのディレクトリを

  • templates (テンプレート)
  • templates_c (コンパイル)

とします。
この、templatesにテンプレート(つまり、HTMLと少量のSmarty構文)を記述します。

templates_c へは、Apacheに書き込み権限を与えてください。(chmod 777 templates_c など)。FTP経由で設置している場合、例えば、FFFTPなら「右クリック」→「属性」のメニューから、書き込みのチェックを入れてください。

これでディレクトリの設定はおしまいです。お疲れ様でした。

Smartyを使うためのPHPファイルの記述

最低限必要なこと

最低限必要なことは、

  1. Smartyクラスのinclude/require
  2. Smartyのディレクトリの設定
  3. 出力

だけです。

<?php

define ('SMARTY_DIR', '/path/to/smarty/'); // 設置したSmarty本体へのパスを設定します(絶対パス)

require_once 'Smarty/Smarty.class.php'; 

$smarty = new Smarty();

$smarty->template_dir = '/path/to/templates/';   // 設置したtemplates  への絶対パス
$smarty->compile_dir  = '/path/to/templates_c/'; // 設置したtemplates_cへの絶対パス


$smarty->display('index.tpl'); // こうすることで、templatesディレクトリにある index.tpl を読み込み、出力する
PHPからテンプレートに表示する変数を代入する

いよいよ、PHP側から、テンプレートに表示するために変数を代入します。

具体的には、assign というメソッドを使って変数を代入します。

<?php

// ... 略

$data = "Hello World!!";
$smarty->assign('hello', $data);

// ... 略

こうすることで、テンプレートの中で「hello」という変数が使えるようになります。(注意:「data」じゃないよ!!)
使い方は、「テンプレートでPHPで設定された変数を表示する」で!

今後、これを「アサインした」と表現します。

もちろん配列や、オブジェクトもアサインすることができます。

テンプレートを指定して出力する

「最低限必要なこと」のコードの中でも書いてしまいましたが、以下のコードが出力のためのコードとなります。

<?php
// ... 略
$smarty->display('index.tpl');

displayは、templatesディレクトリの中のindex.tplというファイルをテンプレートとし、変数の代入などをすべてし、出力せよ!という命令です。

これでSmartyテンプレートエンジンを利用したプログラムを表示することができるようになりました!


テンプレート側逆引きリファレンス(テンプレートデザイナのための Smarty)

変数

テンプレートでPHPで設定された変数を表示する

PHPでアサインされた変数を、テンプレート側で表示します。

{$hello}

このように、左右を「{」「}」で囲み、その中にアサインされた変数を$つきで書き込みます。
この左右の「{」「}」はデリミタと呼ばれます。このデリミタは設定で変更することができますが、今回はデフォルトの { } 中カッコ1つで囲むこととします。

Smartyのテンプレート内では、 { } の中を、構文・関数・変数と判断します。
$がついていると変数とみなされ、アサインされているものがあれば表示します。

PHP側で例えば、

<?php
// .. 略

$array = array(
	'hello' => 'world',
	'hoge'  => 'fuga',
);
$smarty->assign('array', $array);

などとアサインされたとします。こういった場合、

{$array.hello}

のように、「.(ドット)」を使って配列の要素を指定することができます。配列の配列の配列の・・・となった場合も、「.」を使って連結します。
例:

{$array.hello.1.hoge.fuga}

構文(組み込み関数)

よく使うSmartyの構文(オフィシャルのマニュアルでは組み込み関数と呼ばれています)を紹介します。

コメントアウトする

PHPやHTMLのように、一部をコメントアウトすることができます。

{*  コメントアウト  *}

のように、「*」をつけたもので囲みます。この中に書かれたものは、無視され、出力されません。

デリミタを無視してそのまま表示する

デフォルトの { } がデリミタだと困ったことがあります。
例えば、以下のようにテンプレート内にJavascriptのコードを埋め込んだとき、

function hoge() {
	alert(1);
}

などの { } がデリミタと判断され、Smartyのコンパイルエラーが出てしまいます。

これを防ぐために、literal という構文があります。

<script type="text/javascript">
{literal}
function hoge() {
	alert(1);
}
{/literal}
</script>

などと、literalで囲まれた中身は、Smarty構文・変数だとは判断されなくなります。*1

条件で分岐する(if)

PHPや他の言語のように、ifで分岐を作ることができます。

{if $is_hello == 1}
	<p>こんにちは!こんにちは!</p>
{else}
	<p>こんばんは!こんばんは!</p>
{/if}

上の例では、$is_hello という変数に 1 がアサインされている場合、こんにちは!を出力し、それ以外の場合はこんばんは!を出力します。

複数の条件で分岐したり、elseを省略することもできます。

{if $is_hello == 1}
	<p>こんにちは!こんにちは!</p>
{elseif $is_hello == 2}
	<p>おはよう!おはよう!</p>
{/if}

上の例では、$is_hello が 1 なら「こんにちは!」を、2 なら「おはよう!」を、それ以外なら何も出力しません。

配列をすべてループする

配列をすべて出力したりするには、foreach構文を使うことができます。

{* $alpha = array(1 => 'a', 2 => 'b', 3 => 'c' ...); のように、1から順にアルファベットが入っている場合 *}

<ul>
{foreach from=$alpha item=val key=key}
  <li>{$key} : {$val}</li>
{/foreach}
</ul>

この中で、必須なのは、fromとitemだけです。fromはアサインされた配列で、foreachでループさせる変数を指定します。itemは、ループの中でそのそれぞれの要素の呼び名(一時的な変数名)です。keyは、配列のキーです。

この出力結果は、

  • 1 : a
  • 2 : b

...

というようになります。

おまけ:
配列の中身になにも入っていないとき、上記の例だと、

<ul>
</ul>

だけが出力されてしまいます。
こういったときのために、foreachelse という構文を使うことができます。

<ul>
{foreach from=$aplha item=val key=key}
  <li>{$key} : {$val}</li>
{foreachelse}
  <li>なにもありません</li>
{/foreach}
</ul>

このように使います。

別のテンプレートを埋め込む

ヘッダやグローバルナビゲーションなど、全ページで使うような共通部分は、全テンプレートに書かずに、別ファイルとして記述し、それを埋め込めたら便利なものです。
Smartyでも include 構文を使って、外部ファイルを読み込むことができます。

以下は、ヘッダをフッタを別のテンプレートファイルから読み込む例です。*2 もちろんこれらのファイルはtemplatesディレクトリは中に存在しなければいけません。

<html>
<head>
</head>
<body>
{include file="header.tpl"}
<div id="main">
 ... 中略
</div>
{include file="footer.tpl}
</body>
</html>

これが、例えば index.tpl だったとして、他の、index2.tpl というページがあったとしたら、この同じようにheaderやfooterをincludeすれば、共通の部分のメンテナンス性がよくなります。

修飾子

修飾子の使い方

Smartyの修飾子とは、出力する変数になにかしらの加工をすることのできる、フィルタのようなものです。改行をbrに変換したり、HTMLのエスケープ処理をしたり、日付の出力フォーマットを変更したりすることができます。

修飾子は、変数の後ろに「|」をつけ、その後ろに修飾子、その後ろに「:」で区切り、オプションでパラメータを指定することができます。

以下に、HTMLをエスケープする修飾子を例に説明します。

{$hello|escape:"html"}

このように、

{変数|修飾子:オプション}

とすることで修飾子の指定ができます。*3

また、修飾子は、複数指定することができます。「|」で連続させることにより、左から修飾子が適用されます。

以下の例は、htmlをエスケープしたした後、改行をbrに変換して出力する例です。

{$hello|escape|nl2br}


よく使うものだけかいつまんで説明しますが、その他のオプションパラメータについてはマニュアルをご参照ください。

出力する変数のエスケープ処理をする

一番良く使うものだと思います。使い方の説明でも使いましたが、一応。

{* $hello = "<p>Hello!!</p>" だとします *}

{$hello|escape}
改行をbrタグに変換する

改行をbrタグに変換します。これもよく使いますね。

{$hello|nl2br}
日付の表示方法を変更する

日付のフォーマットを指定します。

{* $timestamp = 20080326003305 など*}
{$timestamp|date_format:"%Y/%m/%d %T"}

このとき、変数の $timestamp には、UNIXタイムスタンプ(つまり、PHPのtime()関数などで得られるような、秒の形式)、またはMySQLのタイムスタンプ型(YYYYMMDDHHMMSS)が入っていなければいけません。

上記の出力例は、

2008/03/26 00:33:05
文字列を置換する

簡単な文字列を置換することができます。例えば、「fuck」を「SWEETS(w)」に変換したいとき、

{* $strings = "Shut the fuck up and write some code." だとする *}
{$strings|replace:"fuck":"SWEETS(w)"}

とします。この出力は、以下のようになります。

Shut the SWEETS(w) up and write some code.
変数が空だった場合のデフォルトの出力を設定する

最後に紹介するのは、便利な default修飾子です。
この修飾子を使うと、変数が設定されてなかったり、空だったりした場合に、デフォルトの文字列を出力することができます。

例えば、タイトルがはいっていなければ「no title」としたい場合*4、以下のようにします。

{$title|default:"no title"}

当然、PHPなので、$title 変数になにも値が設定されていないときに、出力しようとするとエラーが発生します。この修飾子をうまく使うとそのエラーを防ぐことができます。
ちなみに、default修飾子を使わずにifで書いたものは、以下のようになります。

{if $title != ""}
 {$title}
{else}
 no title
{/if}

HTMLヘルパー(カスタム関数)

カスタム関数を使うと、面倒なHTMLを書く作業が少しだけ楽になります。そこらのフレームワークに備わっているような、HTMLヘルパーもどきのようなものを使うことができます。

循環して出力する(テーブルの行の色を交互に変えたりする)

よくあるテーブルデザインで、交互に色が変わったりするヤツありますよね。cycle関数を使うと、それを簡単に実現できます。

<table>
 {foreach from=$data item=val}
 <tr class="{cycle values="odd,even"}">
  <td>{$val.title}</td><td>{$val.price}</td>
 </tr>
 {/foreach}
</table>

上記のようにすると、class="odd" と class="even" が交互に出力されます。あとはoddとevenに適当にスタイルシートで色を指定したりなどすればできあがりです。

cycle関数は、呼ばれるたびにvaluesの中身を順に出力します。

ラジオボタンを設定する

配列から、ラジオボタンを出力することができます。

PHP側:

<?php
// .. 略 

$radio = array(
 1 => '',
 2 => '',
);
$smarty->assign('radio', $radio);

テンプレート側:

{html_radios name="sex" values=$radio separator="<br />"}

selectedを指定すると、デフォルトで選択されている項目を指定できます。

{html_radios name="sex" options=$radio separator="<br />" selected=2}
セレクトボックスを設定する

配列から、セレクトボックス(プルダウンメニュー)を出力できます。

PHP側:

<?php
// .. 略 

$select = array(
 1 => '昨日',
 2 => '今日',
 3 => '明日',
);
$smarty->assign('select', $select);

テンプレート側:

{html_options name="day" options=$select selected=2}

これも、selectedを指定するとデフォルトで選択されている項目を指定できます。

チェックボックスを設定する

配列から、チェックボックスを出力できます。

PHP側:

<?php
// .. 略 

$check = array(
 1 => 'お金がほしい',
 2 => '時間がほしい',
 3 => '彼女がほしい',
);
$smarty->assign('check', $check);

テンプレート側:

{html_checkboxes name="want" values=$check separator="/"}

まとめ

超そんなもんです。
本当はもっと色々書こうと思いましたが、一日ではこのあたりで限界です。w 眠気眼で書いているので、間違いがあったら指摘してください。

Smartyは、設置・設定も簡単で、うまく使うと非常に便利なテンプレートエンジンです。*5 まだフレームワークとわからないよ>< でもPHPとHTMLが入り混じるのは見づらいしカッコワルイよ>< とか思ってる方は是非是非入門してみてください。

そして、その段階を過ぎたら、あなたもフレームワークとしてEthnaを使ってみてはいかがですか(え

編集後記

つーか、はてダはアンカーつかえないのか。
そもそもこんなものをはてダで書いたのは間違いだった気が・・・・・・・
気が向いたらそのうちwikiにまとめます。見づらくてすみません。

続きは

書くかもしれないし書かないかもしれないです!

*1:本当はJSの部分を <!-- --> とかで囲むべきなんだけど、なんかはてダのバグで本当にコメントアウトされちゃうから、書いてません。

*2:HTMLがテキトーなのは許してください><

*3:実際には、escape修飾子のパラメータのデフォルトはhtmlに設定されているので、:"html"を指定する必要はありません。

*4:マニュアルの例のまんま><

*5:速度面ではたしかに、symfonyCakePHPのようなPHPを直に書く形式のテンプレートよりも劣りますが。