Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する（6. チケット管理システムを再現➁）

# はじめに
[Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する
（5. チケット管理システムを再現➀）](https://qiita.com/erik_t/items/fff0edee3ddfa509b2a5)の続きです。

# 前提
下記記事で構築した環境を前提とします。

- Windows10にVagrantをを入れてCentOS7をインストールしよう([1](https://qiita.com/erik_t/items/d7f7abbf7deafa4c6fe4)、[2](https://qiita.com/erik_t/items/909efb63fd389f486ec3)、[3](https://qiita.com/erik_t/items/2e3c43cfe8731621b82d)、[4](https://qiita.com/erik_t/items/8d006b599815c8fbf38b)、[5](https://qiita.com/erik_t/items/9fbe7b5630b1f62893a1)、[6](https://qiita.com/erik_t/items/11f24633f4248e4f33f0)) 
- ローカルでLAMP環境を構築しよう（[0](https://qiita.com/erik_t/items/9c7c49db061a250cbc32)、[1](https://qiita.com/erik_t/items/e36235896b327f5cb461)、[2](https://qiita.com/erik_t/items/8dc3f2a5e8e8c9376e27)、[3](https://qiita.com/erik_t/items/617503557020a4a6ba82)、[4](https://qiita.com/erik_t/items/a898d0f547bff6b3d8ff)）
- [CentOS7にComposerをインストールしよう](https://qiita.com/erik_t/items/0b3492f38f6cd8605a4c)

- 私家版 Slim Framework チュートリアル ([1](https://qiita.com/nunulk/items/4b5c15f13ade660cafbc)、[2](https://qiita.com/nunulk/items/8492548678aac697d0aa#_reference-1dc558a7a78d9b00868b)、[3](https://qiita.com/nunulk/items/33adfbba55057a7d0c5c#_reference-8903d1023c2501e00d0b)、[4](https://qiita.com/nunulk/items/fb5ef759c1337e99d878#_reference-56dbec1889beef3f7f4d)、[5](https://qiita.com/nunulk/items/92d06bada7657ce212e7#_reference-1e4198f2501e274dbdd8)、[6](https://qiita.com/nunulk/items/99c12ac8e7b631bd8ed3#_reference-11f698acaecbfe32d5ff))
[@nunulk](https://qiita.com/nunulk)さんのチュートリアルを一通り。
ここで作成したDBを使いまわします。
- Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する([1](https://qiita.com/erik_t/items/14d0103e343e440f6dc5)、[2](https://qiita.com/erik_t/items/9d896867234c904409de)、[3](https://qiita.com/erik_t/items/308091f436e74e2a232e)、[4](https://qiita.com/erik_t/items/7571f214142be628afac)、[5](https://qiita.com/erik_t/items/fff0edee3ddfa509b2a5)）

# 手順
~~1. 専用のユーザーを作成~~
~~2. プロジェクトディレクトリを作成・slim3インストール~~
~~3. 各種設定~~
~~4. DocumentRootを変更＆表示確認~~
~~5. Twigを使ってみよう~~
~~6. Loggingしてみよう~~
~~7. Controllerを作成しよう~~
~~8. PDOを使用してデータベースに接続しよう~~
**9. @nunulkさんのチュートリアルで作成したチケット管理システムをtwigを使って再現しよう**

# やってみよう
今回の記事では、手順9の続きを行います。
## 9. @nunulkさんのチュートリアルで作成したチケット管理システムをtwigを使って再現しよう
### Controllerクラスの残りを実装
Controllerクラスの残りを実装します。

```:src/Action/TicketAction.php
<?php

namespace App\Action;

use App\Domain\Ticket\TicketRepository;
use App\Domain\Ticket\TicketService;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Request;
use Slim\Http\Response;

final class TicketAction extends Action
{
    public function index(Request $request, Response $response)
    {
        $repository = new TicketRepository($this->db);
        $service = new TicketService($repository);
        $tickets = $service->getTickets();
        $data = ['tickets' => $tickets];
        return $this->twig->render($response, 'tickets/index.twig', $data);
    }

    public function create(Request $request, Response $response)
    {
      return $this->twig->render($response, 'tickets/create.twig');
    }

    public function store(Request $request, Response $response)
    {
      $repository = new TicketRepository($this->db);
      $service = new TicketService($repository);
      $subject = $request->getParsedBodyParam('subject');
      $result = $service->insertTicket($subject);
      return $response->withRedirect('/tickets');
    }

    public function show(Request $request, Response $response, array $args)
    {
      $repository = new TicketRepository($this->db);
      $service = new TicketService($repository);
      try {
        $ticket = $service->getTicketById($args['id']);
      } catch (\Exception $e) {
        return $response->withStatus(404)->write($e->getMessage());
      }
      $data = ['ticket' => $ticket];
      return $this->twig->render($response, 'tickets/show.twig', $data);
    }

    public function edit(Request $request, Response $response, array $args)
    {
      $repository = new TicketRepository($this->db);
      $service = new TicketService($repository);
      try {
        $ticket = $service->getTicketById($args['id']);
      } catch (\Exception $e) {
        return $response->withStatus(404)->write($e->getMessage());
      }
      $data = ['ticket' => $ticket];
      return $this->twig->render($response, 'tickets/edit.twig', $data);
    }

    public function update(Request $request, Response $response, array $args)
    {
      $repository = new TicketRepository($this->db);
      $service = new TicketService($repository);
      try {
        $ticket = $service->getTicketById($args['id']);
      } catch (\Exception $e) {
        return $response->withStatus(404)->write($e->getMessage());
      }
      $ticket['subject'] = $request->getParsedBodyParam('subject');
      $result = $service->updateTicket($ticket);
      return $response->withRedirect("/tickets");
    }

    public function delete(Request $request, Response $response, array $args)
    {
      $repository = new TicketRepository($this->db);
      $service = new TicketService($repository);
      try {
        $ticket = $service->getTicketById($args['id']);
      } catch (\Exception $e) {
        return $response->withStatus(404)->write($e->getMessage());
      }
      $result = $service->deleteTicket($ticket['id']);
      return $response->withRedirect("/tickets");
    }
}
```
### routes.phpに追記
`config/routes.php`に以下を追記します。

```:config/routes.php
$app->get('/tickets/create', \App\Action\TicketAction::class . ':create');

$app->post('/tickets', \App\Action\TicketAction::class . ':store');

$app->get('/tickets/{id}', \App\Action\TicketAction::class . ':show');

$app->get('/tickets/{id}/edit', \App\Action\TicketAction::class . ':edit');

$app->patch('/tickets/{id}', \App\Action\TicketAction::class . ':update');

$app->delete('/tickets/{id}', \App\Action\TicketAction::class . ':delete');
```
### twigで残りの画面を実装しよう
#### header.twig作成
タイトルを可変にするため、`templates/header.twig`を作成します。

```:templates/header.twig
<div class="card">
  <div class="card-body">
    <h2 class="card-title">{{ title }}</h2>
    <div class="card-text">
```
#### index.twig作成
header.twigを適用します。header.twigの変数`title`にチケット一覧を代入しています。

```:templates/tickets/index.twig
{% extends 'base.twig' %}
{% block content %}
  {% include 'header.twig' with {'title': 'チケット一覧'} %}
       <a href="/tickets/create">新規作成</a>
        <ul class="list-group">
          {% for ticket in tickets %}
            <li class="list-group-item">
              <a href="/tickets/{{ticket.id}}">
                {{ticket.subject|escape('html')}}
              </a>
            </li>
          {% endfor %}
        </ul>
      </div>
    </div>
  </div>
{% endblock %}
```
#### show.twig作成
header.twigを適用します。header.twigの変数`title`にチケット詳細を代入しています。

```:templates/tickets/show.twig
{% extends 'base.twig' %}
{% block content %}
  {% include 'header.twig' with {'title': 'チケット詳細'} %}
        <table class="table table-bordered">
          <thread>
            <tr>
              <th>ID</th>
              <th>件名</th>
            </tr>
          </thread>
          <tbody>
            <tr>
              <td>{{ticket.id|escape('html')}}</td>
              <td>{{ticket.subject|escape('html')}}</td>
            </tr>
          </tbody>
          <tfoot>
            <tr>
              <td colspan="2">
                <a href="/tickets/{{ticket.id|escape('html')}}/edit" class="btn btn-primary" >編集</a>
                <button class="btn btn-danger" data-toggle="modal" data-target="#deleteModal">削除</button>
              </td>
            </tr>
          </tfoot>
        </table>
      </div>
    </div>
  </div>
  <div class="modal fade" id="deleteModal" tableindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">チケットの削除</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="modal-body">
          <p>本当に削除してよろしいですか？</p>
        </div>
        <form method="post" action="/tickets/{{ticket.id|escape('html')}}">
          <input type="hidden" name="_METHOD" value="delete">
          <div class="modal-footer">
            <button type="submit" class="btn btn-danger">削除</button>
            <button type="button" class="btn btn-secondary" data-dismiss="modal">キャンセル</button>
          </div>
        </form>
      </div>
    </div>
{% endblock %}
```
#### subject.twig作成
チケット作成画面とチケット編集画面は似てるので、テンプレートを作ります。
引数に件名とボタンの名前を渡します。

```:templates/subject.twig
        <div class="form-group">
          <label for="subject">件名</label>
          <input type="text" name="subject" id="subject" class="form-control" value="{{ subject }}">
        </div>
      </div>
    </div>
    <div class="card-body">
      <button class="btn btn-primary">{{ button }}</button>
    </div>
  </div>
</form>
```
本当はembedを使ってみたかったのですが、使い方がよくわかりませんでした...

#### create.twig作成
header.twigとsubject.twigを適用します。
header.twigの変数`title`にチケット作成を代入しています。
create.twigの変数`button`に作成を代入しています。`subject`に引き継ぐ値はないので、何も渡しません。

```:templates/tickets/create.twig
{% extends 'base.twig' %}
{% block content %}
  <form method="POST" action="/tickets">
     {% include 'header.twig'  with {'title': 'チケット作成'} %}
     {% include 'subject.twig' with {'button': '作成'} %}
{% endblock %}
```

#### edit.twig作成
header.twigとsubject.twigを適用します。
header.twigの変数`title`にチケット編集を代入しています。
create.twigの変数`subject`に引き継いだ件名、`button`に編集を代入しています。

```:templates/tickets/create.twig
{% extends 'base.twig' %}
{% block content %}
  <form method="POST" action="/tickets/{{ticket.id|escape('html')}}">
     <input type="hidden" name="_METHOD" value="patch">
     {% include 'header.twig' with {'title': 'チケット編集'} %}
     {% include 'subject.twig' with {'subject': ticket.subject|escape('html'), 'button': '編集'} %}
{% endblock %}
```

#### 動作確認
ブラウザで以下のURLを開いて、一通りの機能が動くか確認してみてください。

```
http://192.168.33.90/tickets
```
# 参考サイト
[Creating your first Slim 3 Framework Application](https://odan.github.io/2017/11/30/creating-your-first-slim-framework-application.html)
[Creating your first Slim 3 Framework Application Part 2](https://odan.github.io/2019/03/18/creating-your-first-slim-framework-application-part-2.html)
私家版 Slim Framework チュートリアル ([1](https://qiita.com/nunulk/items/4b5c15f13ade660cafbc)、[2](https://qiita.com/nunulk/items/8492548678aac697d0aa#_reference-1dc558a7a78d9b00868b)、[3](https://qiita.com/nunulk/items/33adfbba55057a7d0c5c#_reference-8903d1023c2501e00d0b)、[4](https://qiita.com/nunulk/items/fb5ef759c1337e99d878#_reference-56dbec1889beef3f7f4d)、[5](https://qiita.com/nunulk/items/92d06bada7657ce212e7#_reference-1e4198f2501e274dbdd8)、[6](https://qiita.com/nunulk/items/99c12ac8e7b631bd8ed3#_reference-11f698acaecbfe32d5ff))
[[PHP]Twigテンプレートの実践的な構成と作り方](https://php-archive.net/php/twig-advanced/)
[Twig の使い方 - シンプルなチートシート的メモ 2 - テンプレートの分割](http://wolfbash.hateblo.jp/entry/2018/02/14/135647)

# 関連ページ
## Windows10にVagrantをを入れてCentOS7をインストールしよう
[1. VagrantインストールからVagrantfileを設置まで](https://qiita.com/erik_t/items/d7f7abbf7deafa4c6fe4)
[2. 仮想マシンの操作](https://qiita.com/erik_t/items/909efb63fd389f486ec3)
[3. WinSCP、Tera Termに秘密鍵でログイン ](https://qiita.com/erik_t/items/2e3c43cfe8731621b82d)
[4. WinSCP、Tera Termにrootユーザーでパスワードログイン](https://qiita.com/erik_t/items/8d006b599815c8fbf38b)
[5. zip/unzipをインストール](https://qiita.com/erik_t/items/9fbe7b5630b1f62893a1)
[6. Vagrantにて仮想環境を配布](https://qiita.com/erik_t/items/11f24633f4248e4f33f0)

## ローカルでLAMP環境を構築しよう
[0. 事前準備](https://qiita.com/erik_t/items/9c7c49db061a250cbc32)
[1. Apacheをインストール](https://qiita.com/erik_t/items/e36235896b327f5cb461)
[2. MySQLをインストール](https://qiita.com/erik_t/items/8dc3f2a5e8e8c9376e27)
[3. PHPをインストール](https://qiita.com/erik_t/items/617503557020a4a6ba82)
[4. ファイアウォールとか停止する](https://qiita.com/erik_t/items/a898d0f547bff6b3d8ff)

## Composerをインストール
[CentOS7にComposerをインストールしよう](https://qiita.com/erik_t/items/0b3492f38f6cd8605a4c)

## PHP Slim3フレームワークのサンプルアプリを作ろう
[2-1. First Application Walkthrough Getting Set Upまで](https://qiita.com/erik_t/items/9e9f6c93d2403ac90242)

## Apache
 [DocumentRootを変更しよう](https://qiita.com/erik_t/items/d8f4746d2dc2992f329e)

## Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する
[1. プロジェクト作成～各種設定](https://qiita.com/erik_t/items/14d0103e343e440f6dc5)
[2. DocumentRoot変更～Twigを使用](https://qiita.com/erik_t/items/9d896867234c904409de)
[3. LoggingとController](https://qiita.com/erik_t/items/308091f436e74e2a232e)
[4.PDO使用](https://qiita.com/erik_t/items/7571f214142be628afac)
[5. チケット管理システムを再現➀](https://qiita.com/erik_t/items/fff0edee3ddfa509b2a5)
6. チケット管理システムを再現➁