これだけは知っておきたい！Smartyの使い方

PHPのテンプレートエンジンであるSmartyを使用してできることをまとめます。
Smartyのインストールは以下の記事を参考にしてください。

[SmartyのインストールからHelloWorldまで](http://qiita.com/sanotyan1202/items/165b6e793493092380cc)

## 1. 変数
PHPからテンプレートへ値を渡すために変数に格納します。
変数に値を格納するにはSmartyクラスのassign(変数名, 値)を使います。

```php
require_once("Smarty/libs/Smarty.class.php");
$smarty = new Smarty();
$smarty->template_dir = "../smarty/templates/";
$smarty->compile_dir = "../smarty/templates_c/";

// 変数名"name"に"World"を格納する
$smarty->assign("name", "World");

// テンプレートを表示する
$smarty->display("hello.tpl");
```
テンプレート側では{$変数名}という指定をします。

```html:hello.tpl
Hello {$name}!
```
実行結果は以下のようになります。

```:実行結果
Hello World!
```

### 1-1. 配列
以下のようにして配列を渡すことができます。

```php
$ary = array("A", "B", "C");
$smarty->assign("ary", $ary);
```
テンプレートには以下のように記述します。

```テンプレート
Hello {$ary[0]},{$ary[1]},{$ary[2]}!
```
実行結果は以下のようになります。

```:実行結果
Hello A,B,C!
```

### 1-2. 連想配列
以下のようにして連想配列を渡すことができます。

```php
$ary = array("name"=>"taro", "address"=>"Tokyo");
$smarty->assign("ary", $ary);
```
テンプレートには以下のように記述します。

```:テンプレート
名前：{$ary.name}
住所：{$ary.address}
```
実行結果は以下のようになります。

```:実行結果
名前：taro
住所：Tokyo
```
{$配列名["キー名"]}ではアクセスできないので注意してください。

### 1-3. オブジェクト
変数としてオブジェクトを渡すことができます。
以下のようなUserクラスがあるとします。

```php
class User
{
  public $name;
  public $address;

  public function __construct($name, $address)
  {
      $this->name = $name;
      $this->address = $address;
  }

  public function sayHello()
  {
    return "Hello!";
  }
}
```
Userクラスのインスタンスをassignメソッドに指定します。

```php
require_once("User.php");
$usr = new User("taro", "Tokyo");
$smarty->assign("usr", $usr);
```
テンプレートには以下のように記述します。

```:テンプレート
名前：{$usr->name}
住所：{$usr->address}
メッセージ：{$usr->sayHello()}
```
実行結果は以下のようになります。

```:実行結果
名前：taro
住所：Tokyo
メッセージ：Hello!
```
### 1-4. 予約変数

テンプレートでは$_GETのようなスーパーグローバル変数を使うことができます。 
その場合、他の変数のようにassignメソッドを使って渡す必要はありません。
。

|構文|概要|例|
|:--|:--|:--|
|{$smarty.get.パラメータ名}|$_GETに相当|{$smarty.get.id}|
|{$smarty.post.パラメータ名}|$_POSTに相当|{$smarty.post.name}|
|{$smarty.cookiesパラメータ名}|$_COOKIESに相当|{$smarty.cookies.mail}|
|{$smarty.session.パラメータ名}|$_SESSIONに相当|{$smarty.session.userid}|
|{$smarty.server.パラメータ名}|$_SERVERに相当|{$smarty.server.HTTP_USR_AGENT}|

## 2. 修飾子
「|（パイプ）」を用いることでテンプレートの出力フォーマットなどを指定することができます。

```
{$変数名|修飾子名:パラメータ}
```

### 2-1. フォーマット指定
日付や文字列のフォーマットを指定することができます。

```:テンプレート
本日：{$smarty.now|date_format:"%Y年 %m月 %d日"}
```
実行結果は以下のようになります。

```:実行結果
本日：2017年 5月 11日
```

### 2-2. エスケープ処理
スクリプトタグなどをエスケープすることができます。

```php
$maq = "<marquee>move";
$smarty->assign("maq", $maq);
```
テンプレートには以下のように記述します。

```:テンプレート
{$maq|escape}
```
実行結果は以下のようになります。

```html:実行結果
&lt;marquee&gt;move
```
XSS対策としても有効です。

### 2-3. デフォルト指定
変数が空だった場合にデフォルト値を設定することができます。

```php
$name1 = "Taro";
$name2 = "";
$smarty->assign("name1", $name1);
$smarty->assign("name2", $name2);
```
テンプレートには以下のように記述します。

```:テンプレート
{$name1|default:"NONAME"}
{$name2|default:"NONAME"}
```
実行結果は以下のようになります。

```:実行結果
Taro
NONAME
```
## 3. 関数
以下のように記述することで関数を用いることができます。

```:テンプレート
1.{関数名[属性名1="属性値1"] [属性名2="属性値2"]}
2.{関数名[属性名1="属性値1"] [属性名2="属性値2"]} ~ {/関数名}
```


### 3-1. if
条件分岐を用いるには以下のように記述します。

```php
$lang = "PHP";
$smarty->assign("lang", $lang);
```
テンプレートには以下のように記述します。

```:テンプレート
{if $lang == "PHP"}
  PHPです。
{elseif $lang == "Java"}
  Javaです。
{else}
  その他です。
{/if}
```
実行結果は以下のようになります。

```:実行結果
PHPです。
```

### 3-2. foreach
配列などを変数に渡した場合は繰り返し構文を利用することができます。

```php
$names = array("Taro", "Hanako", "John");
$smarty->assign("names", $names);
```

テンプレートには以下のように記述します。

```:テンプレート
{foreach from=$names item="name"}
  {$name},
{/foreach}
```
実行結果は以下のようになります。

```:実行結果
Taro,Hanako,John
```
また、キーを持たせることもできます。

```:テンプレート
{foreach from=$names key="k" item="name"}
  {$k}:{$name},
{/foreach}
```
実行結果は以下のようになります。

```:実行結果
0:Taro,1:Hanako,2:John
```

### 3. include
ヘッダやメニュー、フッタなど共通的なレイアウトを埋め込むことができます。
ヘッダのテンプレートを定義します。

```html:header.tpl
<html>
  <head>
    <meta charset="utf-8">
    <title>Smarty!</title>
  </head>
  <body>
```

フッタのテンプレートを定義します。

```html:footer.tpl
  </body>
</html>
```

Body部のテンプレートでinclude関数を呼び出します。

```html:body.tpl
{include file="header.tpl"}
  ボディです。
{include file="footer.tpl"}
```
実行結果は以下のようになります。

```html:実行結果
<html>
  <head>
    <meta charset="utf-8">
    <title>Smarty!</title>
  </head>
  <body>
    ボディです。
  </body>
</html>
```
## 4. コメント
HTMLのコメントはクライアントが閲覧可能であるため、無闇に入力することができません。
Smartyでは画面に表示されないコメント機能を提供しています。

```:テンプレート
{* コメントです *}
```

実行結果には何も出力されません。

## 5. Config
アプリケーションの設定情報を外部のテキストファイルに書き出しておくことができます。
config/hello.confファイルを作成します。

```
プロジェクト名/smarty/config/hello.conf
```
hello.confファイルに設定情報を記述します。
実際にはDBへの接続情報などを記述するのに適しています。

```:hello.conf
title="Hello Smarty!"
bgcolor="#eeeeee"
```

Smartyインスタンスにconfigディレクトリのパスを設定します。

```php:hello.php
// Configファイルのパスを設定する
$smarty->config_dir = "../smarty/config/";

// hello.confを読み取る(バージョン2系ではconfig_load())
$smarty->configLoad("hello.conf");

// 各設定情報を取得する(バージョン2系ではget_config_vars())
$title = $smarty->getConfigVars("Title");
$bgcolor = $smarty->getConfigVars("bgcolor");

// テンプレートに値を渡す
$smarty->assign("title", $title);
$smarty->assign("bgcolor", $bgcolor);

// テンプレートを表示する
$smarty->display("hello.tpl");
```

テンプレートファイルには以下のように記述します。

```html:hello.tpl
<html>
  <head>
    <title>{$title}</title>
  </head>
  <body bgcolor="{$bgcolor}">
  </body>
</html>
```

実行結果は以下のようになります。

```:実行結果
<html>
  <head>
    <title>"Hello Smarty!</title>
  </head>
  <body bgcolor="#eeeeee">
  </body>
</html>
```

テンプレートから設定情報を読み取るにはconfig_load関数を利用し、{$smarty.config.設定名}でアクセスします。

```html:hello.tpl
{config_load file="hello.conf"}
<html>
  <head>
    <title>{$smarty.config.title}</title>
  </head>
  <body bgcolor="{$smarty.config.bgcolor}">
  </body>
</html>
```

実行結果は先ほどと同様です。