Help us understand the problem. What is going on with this article?

Twigで作るテンプレート兼モックアップ

概要

  • Q. モックアップHTMLはモックとしての機能を維持したまま、テンプレートとして動的ページを生成出来るのか?
  • A. 出来る 出来るのだ そう、Twigならね
  • 用意するもの:Laravel 5.8rcrowe/TwigBridge 0.11.0を組み合わせてTwigを表示できる環境と知識

HTMLファイルをTwig処理する設定

Twigテンプレートエンジンで処理する拡張子は通常だとtwigだが、変更できる。

/foo/config/twigbridge.php
        // 'extension' => 'twig',
        'extension' => 'twig.html',

モックアップ

(比較用。読み飛ばしてOK)

  • 適当に php artisan make:controller してビューを指定
  • /routes/web.php でルーティングを指定
  • ビューファイルを作成 /foo/resources/views/student/detail.twig.html
/foo/app/Http/Controllers/StudentDetail.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Student;

class StudentDetail extends Controller
{
    /**
     * Handle the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function __invoke(int $id)
    {
        $st = [];
        return view('student/detail', ['student' => $st]);
    }
}

/foo/resources/views/student/detail.twig.html
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Laravel</title>
    </head>
    <body>
        <p>home URL</p>
        <p>current URL</p>
        <table border="1">
            <tr>
                <th>ID</th>
                <td>12345</td>
            </tr>
            <tr>
                <th>Name名前</th>
                <td>田中 太郎</td>
            </tr>
            <tr>
                <th>Birthday誕生日</th>
                <td>2001/01/30</td>
            </tr>
        </table>
    </body>
</html>

はい、モック 一丁!
スクリーンショット 2019-03-25 2.40.38.png

標準的なTwigテンプレート

(比較用。読み飛ばしてOK)

標準的なTwigテンプレートの文法で、上記のモックアップを動的ページに書き換えた例。

/foo/resources/views/student/detail-1.twig.html
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>
    </head>
    <body>
        <p>{{ url('/home') }}</p>
        <p>{{ url().current() }}</p>
        <table border="1">
            <tr>
                <th>ID</th>
                <td>{{ student.id }}</td>
            </tr>
            <tr>
                <th>Name名前</th>
                <td>{{ student.name }}</td>
            </tr>
            <tr>
                <th>Birthday誕生日</th>
                <td>{{ student.birthday|date("Y/m/d") }}</td>
            </tr>
        </table>
    </body>
</html>

/foo/app/Http/Controllers/StudentDetail.php
    public function __invoke(int $id)
    {
        $st = ['id' = 2, 'name' => '田中', 'birthday' => '2000-01-01'];
        // Eloquent使ってDBから取得しても、ええんやで
        // $st = Student::findOrFail($id);
        return view('student/detail-1', ['student' => $st]);
    }

はい、動的ページ 一丁!
スクリーンショット 2019-03-25 2.57.55.png

テンプレート兼モックアップ

  • 要するに(1)HTMLコメントでTwigを制御して(2)TwigコメントをHTML出力すればいい
  • Twig Lexerを変更すれば可能
/foo/app/Http/Controllers/StudentDetail.php
    public function __invoke(int $id)
    {
        $st = Student::findOrFail($id);

        $twig = \Twig::getFacadeApplication()->get('twig');
        $lexer = new \Twig\Lexer($twig, [
            // 本来のdelimiter
            // 'tag_comment'   => ['{#', '#}'],
            // 'tag_block'     => ['{%', '%}'],
            // 'tag_variable'  => ['{{', '}}'],
            // 'interpolation' => ['#{', '}'],
            // 変更したdelimiter
            'tag_comment'   => ['<!-- {# -->', '<!-- #} -->'],
            'tag_block'     => ['<!-- {%', '%} -->'],
            'tag_variable'  => ['<!-- {{', '}} -->'],
            'interpolation' => ['<!-- #{', '} -->'],
        ]);
        $twig->setLexer($lexer);

        return view('student/detail-2', ['student' => $st]);
    }
/foo/resources/views/student/detail-2.twig.html
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>
    </head>
    <body>
        <p><!-- {# -->home URL<!-- #} --><!-- {{ url('/home') }} --></p>
        <p><!-- {# -->current URL<!-- #} --><!-- {{ url().current() }} --></p>
        <table border="1">
            <tr>
                <th>ID</th>
                <td><!-- {# -->12345<!-- #} --><!-- {{ student.id }} --></td>
            </tr>
            <tr>
                <th>Name名前</th>
                <td><!-- {# -->田中 太郎<!-- #} --><!-- {{ student.name }} --></td>
            </tr>
            <tr>
                <th>Birthday誕生日</th>
                <td><!-- {# -->2001/01/30<!-- #} --><!-- {{ student.birthday|date("Y/m/d") }} --></td>
            </tr>
        </table>
    </body>
</html>

テンプレートエンジンを通さない場合、モックアップと同様に見える。
スクリーンショット 2019-03-25 3.06.39.png

テンプレートエンジンを通した場合、標準的なTwigの出力と同様に見える。
スクリーンショット 2019-03-25 3.03.17.png

注意

Lexerを変更した後は php artisan twig:cleanキャッシュを削除すること。
 Twigはテンプレートファイルにアクセスした時に、phpキャッシュを作成してHTMLレンダリングに使用する。テンプレートファイルが変更されていたらphpキャッシュを作り直してレンダリングする。
 上述の方法でLexerを変更しても、キャッシュは再生成されず、Lexerが変更されていない状態のキャッシュでHTMLレンダリングが行われるので、Lexerを何回変更しても変更が反映されない、ように見える。

雑感

Twig is神

Hope this helps.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした