Smarty3 + CakePHP3 でらくらくファイル出力

## やりたいこと
テンプレートファイルを用意して、ユーザーがフォームから入力した値を埋め込みたい！
そして値を埋め込んだ結果をファイル出力したい！

## 環境
CakePHP: 3.5.6
CentOS: 7.4
Smarty: 3.1

Smartyを触ったことがなかったので、触ってみることに。

## 手順

### Smartyのセットアップ

#### composerにてインストール
```
composer require smarty/smarty:~3.1
```

#### ディレクトリ作成

```
smarty-sample/  ・・・CakeのROOTディレクトリ
　　smarty/
　　　　templates/　　・・・テンプレートファイル(.tpl)の設置先
　　　　templates_c/　　・・・コンパイル結果出力先
　　　　cache/　・・・キャッシュファイル出力先
　　files/  ・・・テンプレート埋め込み後のファイル保存先
```

apacheユーザーが書き込めるようにします。

```
chmod 0777 smarty/templates_c smarty/cache/
chmod 0777 files
```

#### PATHの設定

利用しやすいようにpaths.phpに書いちゃいましょう。

```
// config/paths.phpに追記
# Smarty用ディレクトリ
define('SMARTY_TEMPLATE_DIR', ROOT . DS . 'smarty' . DS . 'templates' . DS);
define('SMARTY_COMPILE_DIR', ROOT . DS . 'smarty' . DS . 'templates_c' . DS);
define('SMARTY_CACHE_DIR', ROOT . DS . 'smarty' . DS . 'cache' . DS);
define('SMARTY_CONFIG_DIR', ROOT . DS . 'smarty' . DS . 'config' . DS);

# ファイル出力用ディレクトリ
define('FILE_DIR', ROOT . DS . 'files' . DS);
```

####  クラスの拡張


```
<?php
namespace App\Lib;

use Smarty;

class AppSmarty extends Smarty
{

    function __construct()
    {
        parent::__construct();

		// paths.phpに書いた値を使って初期化
        $this->template_dir = SMARTY_TEMPLATE_DIR;
        $this->compile_dir = SMARTY_COMPILE_DIR;
        $this->config_dir = SMARTY_CONFIG_DIR;
        $this->cache_dir = SMARTY_CACHE_DIR;
    }

}

?>
```

これでAppSmartyをuseしてあげれば利用可能です！


## サンプル
えいやっとサンプルを作りました。

#### tplファイル

**smarty/templates/hello.tpl**

```
私の名前は {$name} です!

{$comment}

◯ 食べたいもの
{foreach $favorites as $key => $val}
・{$val}
{/foreach}
```

**smarty/templates/hello2.tpl**

```
名前: {$name}
コメント: {$comment}
好きな食べ物:
{foreach $favorites as $key => $val}
    ・{$val}
{/foreach}
```

配列を渡すこともできます。

#### Controller

**TutorialController.php**

```
<?php
namespace App\Controller;

use App\Controller\AppController;

// AppSmartyの読み込み
use App\Lib\AppSmarty;
use Cake\Filesystem\File;

class TutorialController extends AppController
{
    public function add()
    {

        if ($this->request->is('post')) {
            // 1. インスタンスを作成
            $smarty = new AppSmarty();

            // 2. リクエストデータを変数を割り当て
            // $this->assign(template内変数, 割り当てる値)
            foreach ($this->request->getData() as $key => $val) {
                $smarty->assign($key, $val);
            }

            // 3. fetch('template file')で変数の割当後の値を取得
            // assignした値を使って複数のtemplateを利用することができる
            $hello1 = $smarty->fetch('hello1.tpl');
            $hello2 = $smarty->fetch('hello2.tpl');

            // 4. Fileユーティリティを利用して結果を出力
            (new File(FILE_DIR . 'hello1.txt'))->write($hello1);
            (new File(FILE_DIR . 'hello2.txt'))->write($hello2);
        }

    }
}
```

#### View
**add.ctp**

```
<fieldset>
    <?= $this->Form->create(
        null,
        [
            'url' => [
                'controller' => 'Tutorial',
                'action' => 'add'
            ]
        ]) ?>
    <?= $this->Form->input('name') ?>
    <?= $this->Form->input('comment') ?>

    <?= $this->Form->select(
        'favorites',
        [
            ['text' => 'カレー', 'value' => 'カレー'],
            ['text' => 'カツ丼', 'value' => 'カツ丼'],
            ['text' => '焼肉', 'value' => '焼肉'],
        ],
        [
            'multiple' => 'checkbox'
        ]
    ) ?>

    <?= $this->Form->button(__('submit')) ?>
    <?= $this->Form->end() ?>
</fieldset>
```

現在21:30。食欲がctpファイルに如実に現れています。

## postしてみる

<img width="693" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/99116/3a1312dc-bf9a-91c5-dec7-6d432ac19ed1.png">

Let's post！！

## 結果

```
[fusic@localhost smarty-sample]$ cat files/hello1.txt
私の名前は koga です!

お腹すいた。。

◯ 食べたいもの
・カレー
・焼肉

[fusic@localhost smarty-sample]$ cat files/hello2.txt
名前: koga
コメント: お腹すいた。。
好きな食べ物:
　・カレー
　・焼肉
```
値が埋め込まれた結果がちゃんと出力されました！！


## まとめ
- SmartyとFileユーティリティで簡単にファイル出力できました！
- templateの工夫次第で色々できるかも？

## 参考リンク

[Smarty3 マニュアル](https://www.smarty.net/docs/ja/)
[Folder & File](https://book.cakephp.org/3.0/ja/core-libraries/file-folder.html)