Twigとは。インストールから継承まで


TwigとはPHPのテンプレートエンジン。

### インストール

```
composer require "twig/twig:~1.0"
```

実行結果(Windows)。

```
C:\tmp>composer require "twig/twig:~1.0"
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.or
g/xdebug
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing twig/twig (v1.24.0)
    Loading from cache

Writing lock file
Generating autoload files
```

### テンプレートファイルにデータを渡す

動作確認のため以下の2つのファイルを作成。

- sample.html.twig
 - HTMLを記述、MVCでいうとビューとなる。
- sample.php
 - ビューを呼び出す。MVCでいうとコントローラ部分のイメージ。（サンプルデータも設定しているが）

```sample.html.twig
<html>
    <head>
        <title>{{ title }}</title>
    </head>
    <body>
        <h1>{{ message }}</h1>
    </body>
</html>
```


```sample.php
<?php
require_once 'vendor/autoload.php';

// テンプレートファイルがあるディレクトリ（本サンプルではカレントディレクトリ）
$loader = new Twig_Loader_Filesystem('.');

$twig = new Twig_Environment($loader);

$template = $twig->loadTemplate('sample.html.twig');
$data = array(
    'title' => 'sample',
    'message'  => 'My Webpage!',
);
echo $template->render($data);
?>
```

今回は簡単に試せるように、WEBサーバ経由でなく、直接実行してテンプレートファイルが動的に生成されることを確認する。

なお、ディレクトリ構成は下記となっている。

```tree(抜粋)
C:.
│  composer.json
│  composer.lock
│  sample.html.twig
│  sample.php
│
└─vendor
    │  autoload.php
    │
    ├─composer
    │
    └─twig
        └─twig
```

下記のとおりsample.phpを実行

```
php sample.php
```

実行結果

```
C:\tmp>php sample.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>
        <h1>My Webpage!</h1>
    </body>
</html>
```

きちんと変換されています。
渡した変数が{{title}}と{{message}}に展開されている。

### 配列を利用した繰り返し

次は配列データのループの確認です。

```sample2.html.twig
<html>
    <head>
        <title>{{ title }}</title>
    </head>
    <body>
        <h1>{{ message }}</h1>
        <table>
           {% for user in users %}

           <tr>
              <td>{{ user.id }}</td>
              <td>{{ user.name }}</td>
              <td>{{ user.tel }}</td>
           </tr>
           {% endfor %}

        </table>
    </body>
</html>
```

```sample2.php
<?php
require_once 'vendor/autoload.php';

$loader = new Twig_Loader_Filesystem('.');

$twig = new Twig_Environment($loader);

$template = $twig->loadTemplate('sample2.html.twig');
$data = array(
    'title' => 'sample2',
    'message'  => 'My Webpage 2!',
    'users' => [['id'=>123, 'name'=>'Yamada', 'tel'=>'03-1234-xxxx'],
                ['id'=>456, 'name'=>'Tanaka', 'tel'=>'03-1234-yyyy']]
);
echo $template->render($data);
?>
```

実行結果

```
C:\tmp>php sample2.php
<html>
    <head>
        <title>sample2</title>
    </head>
    <body>
        <h1>My Webpage 2!</h1>
        <table>

           <tr>
              <td>123</td>
              <td>Yamada</td>
              <td>03-1234-xxxx</td>
           </tr>

           <tr>
              <td>456</td>
              <td>Tanaka</td>
              <td>03-1234-yyyy</td>
           </tr>

        </table>
    </body>
</html>
```

### テンプレートの継承

最後にテンプレートの継承を確認。

上記と同じデータをテンプレートを継承する構成で作成します。

まずベースとなるテンプレートファイルを作成し、可変部分をblockで定義します。

子となるファイルは基本的に画面ごとに作成されます。
各画面独自の部分をベースで定義したblockとして記述します。
子テンプレートファイルはblockのみから構成されます。

ちなみにテンプレートファイル内では
{#コメント#}
がコメントです。

まずは親となるベーステンプレートファイル。

親のブロック内にデフォルトとなる値を書いておくこともできます。
子で同じブロックを記述すると上書きされます。
ただし、parent()で親の内容を参照することもできます。

```base.html.twig
<html>
    <head>
        <title>{% block title %}{% endblock %}</title>
{% block javascript %}
        <script type="text/javascript" src="hoge.js"></script>
{% endblock %}
    </head>
    <body>
        <h1>{% block header %}{% endblock %}</h1>
        {% block main %}{% endblock %}
    </body>
</html>
```

次に子供となるテンプレートファイル

```sample3.html.twig
{# ベースとなるテンプレートを継承する #}
{% extends "base.html.twig" %}

{% block title %}{{ title }}{% endblock %}

{# parent()で親のJSに子のJSも追加している #}
{% block javascript %}
{{ parent() }}
<script type="text/javascript" src="fuga.js"></script>
{% endblock %}

{% block header %}{{ message }}{% endblock %}

{% block main %}
        <table>
           {% for user in users %}

           <tr>
              <td>{{ user.id }}</td>
              <td>{{ user.name }}</td>
              <td>{{ user.tel }}</td>
           </tr>
           {% endfor %}

        </table>
{% endblock %}
```

実行ファイル

```sample3.php
<?php
require_once 'vendor/autoload.php';

$loader = new Twig_Loader_Filesystem('.');

$twig = new Twig_Environment($loader);

$template = $twig->loadTemplate('sample3.html.twig');
$data = array(
    'title' => 'sample3',
    'message'  => 'My Webpage 3!',
    'users' => [['id'=>123, 'name'=>'Yamada', 'tel'=>'03-1234-xxxx'],
                ['id'=>456, 'name'=>'Tanaka', 'tel'=>'03-1234-yyyy']]
);
echo $template->render($data);
?>
```

実行結果。

```実行結果
C:\tmp>php sample3.php
<html>
    <head>
        <title>sample3</title>
        <script type="text/javascript" src="hoge.js"></script>

<script type="text/javascript" src="fuga.js"></script>
    </head>
    <body>
        <h1>My Webpage 3!</h1>
                <table>

           <tr>
              <td>123</td>
              <td>Yamada</td>
              <td>03-1234-xxxx</td>
           </tr>

           <tr>
              <td>456</td>
              <td>Tanaka</td>
              <td>03-1234-yyyy</td>
           </tr>

        </table>
    </body>
</html>
```

正しく展開されました。
実際のWEBアプリケーションではヘッダ、フッタ、サイドバーなどは共通であることがほとんどだと思うので、このレイアウト昨日は必須ですね。