日記

日々のことと、Python/Django/PHP/Laravel/nodejs などソフトウェア開発のことを書き綴ります

Laravel 5.1 入門記 その9(Blade Templates 編)

今回は Blade Templates に入ります。

Blade Templates - Laravel - The PHP Framework For Web Artisans

ちらちらサンプル的なものが見えてたので、簡単なシンタックスシュガーは飛ばしていきたいところ。

Introduction

Blade テンプレートファイルは resource/views 配下に拡張子 .blade.php を配置して使います。そしてテンプレートファイルは、PHPコンパイルされて、変更があるまではキャッシュを読み込むようです。

Template Inheritance

いきなりテンプレートの継承か…。

<!-- Stored in resources/views/layouts/master.blade.php -->

<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            This is the master sidebar.
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

これがベースになるテンプレート。@yield や @section などをこのベーステンプレートを継承したファイルにおいて記述していきます。続いて、ベースを継承する子供テンプレート。

<!-- Stored in resources/views/layouts/child.blade.php -->

@extends('layouts.master')

@section('title', 'Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

子供のテンプレートでは、親テンプレートになかった @extends で親となるテンプレートを指定しています。そして親テンプレートで定義のあった、 title / sidebar / content を @section で定義してあります。 @section('sidebar') の直後にある @parent は、親テンプレートの section の内容が展開されます。これを書いておくと上書きでは無く、追記する感じになります。

続いて、ルーティングを登録します。

Route::get('blade', function () {
    return view('child');
});

view に渡すべきは子供のテンプレート名です。 そういえば、.blade は要らないんだな。ブラウザで http://localhost:8080/blade にアクセス!

This is the master sidebar.
This is appended to the master sidebar.

This is my body content.

\(^o^)/\(^o^)/\(^o^)/

何か一山越えた感があります。

Displaying Data

Blade テンプレートを使うと、変数の出力のシンタックスも変わります。

{{ $name }}

{{ time() }}

これで $name の出力になります。簡略化されました。time() のようにすると同じやり方で関数の戻り値の表示もできます。

ちなみに {{ }} で出力した内容は、HTML escape が自動的に行われるらしい。HTML escape をさせたくない場合は

{!! $name !!}

という書き方をすれば、そのままの文字列が出力される。

{{ name }} のような表現を Blade に無視させるには @{{ name }} とすれば良いらしい。これで、 {{ name }} がそのまま HTML に表示される。

$name がセットされていないときにデフォルト値を表示したい場合は、

{{ isset($name) ? $name : 'Default' }}

のようにも書けるが

{{ $name or 'Default' }}

と簡略化できる。

Control Structures

If Statements

まぁ、見れば分かるので、こんな感じ。

@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif

unless というのもあるらしい。

@unless (Auth::check())
    You are not signed in.
@endunless
Loops

いくつかループには種類があり、for foreach forelse while がある。これも見れば一目瞭然。

@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users</p>
@endforelse

@while (true)
    <p>I'm looping forever.</p>
@endwhile
Including Sub-Views

要は、Blade テンプレートなどのインクルードですね。書き方はこんな感じ

<div>
    @include('shared.errors')

    <form>
        <!-- Form Contents -->
    </form>
</div>

インクルードする View にパラメータが必要な場合は、次のように書ける。

@include('view.name', ['some' => 'data'])

ちょっと試したいことがあるので、前回作った greeting.php を以下の様に変更します。

Hello, <?php echo $name; ?>. I'm <?php echo $my_name; ?>

compoer_value: <?php echo $composer_value; ?>

html と body タグは外しちゃいました。そして、 child.blade.php も変更

@extends('layouts.master')

@section('title', 'Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
    @include('greeting', ['name' => 'James'])
@endsection

@include('greeting', ['name' => 'James']) というのを追加しました。これで何を試したかったかと言うと、include したときにも View Composer が働くかどうかと言う点。ではブラウザでアクセスしてみると

This is the master sidebar.
This is appended to the master sidebar.

This is my body content.

Hello, James. I'm tnamao

compoer_value: class composer!!

できたー\(^o^)/\(^o^)/\(^o^)/ インクルードしたタイミングでも View Composer は実行されているようですね。

Comments

Blade でのコメントは以下の様な感じ。まぁ、たまに使いたくなりますよね。

{{-- This comment will not be present in the rendered HTML --}}

Service Injection

テンプレートでやるのか… という感じも受けたけど、やり方だけ確認しておきます。

@inject('metrics', 'App\Services\MetricsService')

<div>
    Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>

@inject でサービスクラスを指定し、第1引数がテンプレート内で使う変数名で、第2引数がクラスやインターフェース名とのこと。

Extending Blade

Blade 拡張。要は、ディレクティブの拡張らしい。次の例が datetime をフォーマットしちゃうディレクティブの例のようです。

<?php

namespace App\Providers;

use Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('datetime', function($expression) {
            return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>";
        });
    }

    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

Blade::directive の第1引数で追加するディレクティブ名を指定し、第2引数に Closure を書くらしい。この Closure が返すのは PHP のコードの模様。これをテンプレート上から呼び出すとディレクティブは最終的に次の PHP コードとなって生成される。

<?php echo with($var)->format('m/d/Y H:i'); ?>

ここで使用している with helper は単純に指定された object / value を返すもので、メソッドチェインを行う時に便利らしい。

with helper イマイチ分からなかった…。

締まらない感じですが、これで Blade Templates のセクションも終了!!\(^o^)/

The Basic を一通りやりきったので、続いては Architecture Foundations か、Database のどちらかに進みます。実用的なのは Database かなぁ…。