Laravelの画面表示に使うBladeテンプレートの構文について

  • 2019年12月12日
  • 2020年4月4日
  • Laravel

 

通常PHPで開発するときには表示部分をHTMLで記述しますが、LaravelにはBladeテンプレートという便利なものが用意されています。

Bladeテンプレートでは普通にPHPやHTMLで書のではできない便利な機能がいくつかあります。

そんなBladeテンプレートについてまとめて見たいと思います。

 

Bladeテンプレートで書いてみる

 

では、実際にBladeテンプレートで表示部分を作ってみましょう。作成したファイルは通常resources/views内にフォルダを作って保存しておきます

 

では、resources/viewsの中にhelloというフォルダを作りその中にworld.blade.phpというファイルを用意したとしましょう。(Bladeテンプレートの拡張子は.blade.phpになります。)

world.blade.phpを次のようにしてみましょう。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
{{-- $msgに値をセット --}}
@php
  $msg = 'メッセージ';
@endphp
<p class="message">{{$msg}}</p>
</body>
</html>

はい、通常のHTMLの記述とほとんど変わりません。

違いがあるのは以下の部分です。

 

変数の表示のさせ方

 

ただ、PHPの変数を表示する際に<?php echo $msg;?>とする必要がなく、{{$msg}}という記述で呼べるようになっています。

{{$msg}}

これの利点はPHPがわからない人でもPHPを意識することなくHTMLを記述できる点です。

 

コメントアウト

 

コメントアウトしたいときは{{– と –}}で囲います。

{{-- コメント --}}

この方法でコメントアウトした場合にはweb上のソースにも表示されません。

 

PHPの記述

 

PHPのロジックを書きたいときは<?php〜?>の代わりに@php〜@endphpを使用します。

@php
  PHPの処理
@endphp

 

これら以外にも、Bladeテンプレートでは独自の構文があり、そこでさらに通常のHTMLとの差別化がされています。それについてはあとで紹介します。

 

ルーティングやコントローラからの呼び出し方

 

Bladeテンプレートで記述したファイルに関してはresources/viewsフォルダの中にディレクトリを作ってそこに配置しました。

ファイルが存在してもルーティングによる紐づけがない限り呼び出すことができません。

 

ルーティングから呼ぶ

 

ルーティングから直接Bladeテンプレートのファイルを呼びたい場合は次のようにviewという関数を利用します。

Route::get('hello/world', function () {
  return view('hello.world');
});

 

コントローラ経由で呼ぶ

 

コントローラで処理をしたあとにBladeテンプレートを呼び出したい場合もviewという関数を利用します。

まず、ルーティングでコントローラを呼び出します。

Route::get('hello/world', 'HelloController@world);

コントローラではview関数を呼び出します。

class HelloController extends Controller
{
  public function world() {
    return view('hello.world');
  });
}

これで、ルーティング→コントローラ→Bladeテンプレートという順で呼び出されるようにできました。

 

http://ドメイン名/hello/worldと呼び出せばviewsフォルダの中のさらにhelloフォルダの中にあるworld.blade.phpが呼び出されることがわかります。

 

また、Bladeテンプレート内でコントローラーで取得されたPHPの変数を使いたい場合もあるかと思います。

そんなときは連想配列をview関数の第二引数に渡してあげればOKです。

view('hello.world', ['msg' => $msg]);

 

Bladeテンプレート内で使える構文たち

 

Bladeテンプレート内では独自の構文が用意されていて、PHPの処理をPHPらしくかつPHPがわからない人にも比較的わかりやすく書くことができます。

たくさんあるので、1つずつ見て行きましょう。

 

条件分岐系

 

条件分岐系では@ifディレクティブ@switchディレクティブ@unlessディレクティブ@emptyディレクティブ@issetディレクティブを取り上げます。

 

@if

@ifディレクティブはPHPのif文と同等の動きをします。@ifディレクティブを書きたいときは以下のようにします。

@if (条件1)
  条件1が真のときの出力
@elseif (条件2)
  条件1が偽かつ条件2が真のときの出力
@else
  条件1が偽かつ条件2が偽のときの出力
@endif

これはPHPでif文を書く感覚に似ていますね。

 

@unless

@unlessディレクティブはRubyのunless文と同様に条件が偽のときに処理を行う構文になっています。

@unless (条件)
  条件が偽のときの処理
@else
  条件が真のときの処理
@endunless

elseif的なelseunlessのようなものはないかと思われます。

 

@switch

@switchディレクティブはPHPのswitch文に相当するものです。

@switch (変数)
  @case (0)
    0のときの処理
    @break
  @case (1)
    1のときの処理
    @break
  @default
    その他のときの処理
@endswitch

 

@empty

@emptyディレクティブはif(empty(変数))と同じ動きをします。

@empty (変数)
  変数が0やfalseやnullのときの処理
@else
  変数が0やfalseやnullでないときの処理
@endempty

 

@isset

@issetディレクティブもif(isset(変数))と同じ動きをします。

@isset (変数)
  変数が定義されていてnullでないときの処理
@else
  変数が定義されていないかnullのときの処理
@endisset

PHPのemptyやissetの判定はわかりづらいです。以下サイトに判定結果がまとめられていますので参考にどうぞ。

https://qiita.com/shinichi-takii/items/00aed26f96cf6bb3fe62

 

繰り返し系

 

繰り返し系では@forディレクティブ@foreachディレクティブ@whileディレクティブ@forelseディレクティブを取り上げます。

 

@forディレクティブ、@foreachディレクティブ、@whileディレクティブはPHPのそれぞれの文に対応しますので、難しいことはないと思います。

@for

@for ($i = 0; $i < 10; $i++)
  10回繰り返し
@endfor 

@foreach

@foreach ($array as $value)
  $arrayの繰り返し
@endforeach

@while

@while (条件)
  条件が真のとき繰り返し続ける
@endwhile

 

@forelse

@forelseディレクティブはforeachとほぼ同じですが、変数が繰り返し可能でないときに@emptyディレクティブ内の処理を行ってくれます。

@forelse ($array as $value)
  $arrayに値があるときの処理
@empty
  $arrayが空のときの処理
@endforelse

$arrayに整数型などのそもそも繰り返しができない値が入っている場合や$arrayに値がセットされていない場合はエラーになります。

 

@break,@continue

また繰り返しを抜けたいときには@breakディレクティブ@continueディレクティブも使えます。かっこの中にはbreakやcontinueを実行するときの条件を記述します。

@for ($i = 0; $i < 10; $i++)
  @continue ($i === 2)
  @break ($i === 8)
@endfor

もちろん@ifディレクティブを使って@breakや@continueを単体で使用することもできます。

@for ($i = 0; $i < 10; $i++)
  @if ($i === 2)
    @continue
  @endif
  @if ($i === 8)
    @break
  @endif
@endfor

 

便利な変数$loop

 

Bladeテンプレート内では便利なループに関するプロパティを保持している変数が用意されています。

 

  • $loop->first: ループの最初ならTRUE、それ以外はFALSEを返す
  • $loop->last: ループの最後ならTRUE、それ以外はFALSEを返す
  • $loop->index: 現在のループ数(0からカウント)
  • $loop->iteration: 現在のループ数(1からカウント)
  • $loop->count: ループ回数
  • $loop->remaining: ループの残り回数
  • $loop->depth: 現在のネスト数
  • $loop->parent: 一つ上のネストのループ変数

 

これによってループに関する条件分岐や数値の表示を簡単にすることができます。

@forelse ($array as $value)
  @if ($loop->first)
    <p>最初の値は{{$value}}です</p>
  @elseif ($loop->last)
    <p>最後の値は{{$value}}です</p>
  @else
    <p>{{$loop->iteration}}個目の値は{{$value}}です</p>
  @endif
@empty
  <p>値がありません</p>
@endforelse

 

ビューの表示系

 

これまで、PHPらしい処理をBladeの構文で書くやり方を見てきましたが、Bladeテンプレートではビューの継承とかもサポートされています。

ビューの継承によって親ビューと子ビューに分けて保存したり、共通部分を別のファイルとして保存しておくことができます。

 

@extends

 

@extendsディレクティブは親ビューの内容を子ビューに読み込むために使用します。@extendsは子ビューに記載し、親ビューへのパスを記述します。親ビューはresourcesの中のviewsフォルダ以下の部分を記載します。また区切りはドット(.)で行います。

例えば、親ビューがresources/views/layouts/parent.blade.phpの場合は、

@extends ('layouts.parent')

となります。

 

@yield

 

次は@yieldディレクティブです。こちらは次にある@sectionで定義したものをはめ込むためのものになっています。基本的に親ビューに記述しておき、子ビューの@section〜@endsectionの内容を表示するために使用します。

@yield (セクション名)

 

@section

 

@sectionディレクティブはセクションの内容を記述するものになります。

子ビューに記載した@sectionディレクティブでは親ビューにある同名の@yieldと連携して@yieldがある位置に@sectionの内容が表示されます。

@section (セクション名)
  セクションの内容
@endsection

 

また、@sectionは親ビューでも使えて、@endsectionの代わりに@showを使用することで、セクションを定義しつつ表示することができます。@yieldのように表示用の枠を用意しつつデフォルトの表示内容を記載できるような形です。

@section (セクション名)
  セクションの内容
@show

@section〜@showを親ビューで使い、子ビューで@section〜@endsectionを定義した際には内容が子ビューのもので上書きされます。子ビューで@parentを使用すれば親ビューの@section〜@showの内容を呼び出すことができます。

 

@extendsと@yieldと@sectionを利用した例を見てみましょう。

↓親ビューの内容(resources/views/layouts/parent.blade.php)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>@yield('title')</title>
</head>
<body>
<h1>@yield('title')</h1>
@section('content')
<p>親ビューのコンテンツ</p>
@show
</body>
</html>

 

↓子ビューの内容(resources/views/index.blade.php)

@extends('layouts.parent')

@section('title')
Hello World
@endsection

@section('content')
@parent
<p>子ビューのコンテンツ</p>
@endsection

 

ルーティングにresources/views/index.blade.phpを呼び出すように記述し、アクセスしてみると表示は以下のようになっています。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<p>親ビューのコンテンツ</p>
<p>子ビューのコンテンツ</p>
</body>
</html>

 

@include

 

@includeディレクティブはサブビューと呼ばれていて、テンプレートを読み込むのに使えます。例えばヘッダーに同じ内容を記述したいときにヘッダーだけ別ファイルとして持つことができます。

こちらも@extends同様にファイルへのパスを引き渡してあげます。resources/views/components/header.blade.phpを読み込むとすると、

@include ('components.header')

と書きます。

もし、インクルード先のファイルで変数を使っている場合には、連想配列で引き渡してあげます。

@include ('components.header', ['title' => 'Hello World'])

 

@component

 

@componentディレクティブも同じく、テンプレートを読み込むためのものです。

 

呼び出しは同じくファイルへのパスを引き渡します。

@component ('components.header')
@endcomponent

変数を引き渡したいときは@slotディレクティブを使用します。

@component ('components.header')
  @slot ('title')
    Hello World
  @endslot
@endcomponent

 

 

サブビューとの文法以外の違いは、@componentはHTMLタグを正しく読み込めるのに対し、@includeは正しく読み込めないのだそう。

あと、@componentでは呼び出し元(@componentと書いているファイル)にある変数が呼び出し先(@componentで指定されているファイル)で使えないのに対して、@includeでは使えるそうです。

 

@component @include
HTMLタグを変数に含めたとき タグとして認識 文字列として認識
呼び出し元の変数 使えない 使える

 

@each

 

@eachディレクティブはコレクションビューと呼ばれていて@foreachと@includeを同時に行ってくれるものという感じです。ただ、@eachを使用すると呼び出し元の変数が使えなくなるみたいなので、その時は@foreachと@includeを使って記述する必要があります。

パスと繰り返しをする配列などと配列から取り出した値を入れる変数名を渡してあげます。

@each ('components.items', $array, 'value')

これは以下のようにも書き換えられます。

@foreach ($array as $value)
  @include ('components.items', ['value' => $value])
@endforeach

 

@includeと@componentと@eachの例を見てみましょう。

↓コンポーネントのファイル(resources/views/components/items.blade.php)

<li>{{$item}}</li>

 

↓子ビューの内容(resources/views/index.blade.php)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<h2>include</h2>
<ul>
  @include ('components.items', ['item' => 'include'])
</ul>
<h2>component</h2>
<ul>
  @component ('components.items')
    @slot ('item')
      component
    @endslot
  @endcomponent
</ul>
<h2>each</h2>
<ul>
  @each ('components.items', ['each1', 'each2'], 'item')
</ul>
</body>
</html>

 

すると表示結果は以下の通りになるかと思います。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<h2>include</h2>
<ul>
  <li>include</li>
</ul>
<h2>component</h2>
<ul>
  <li>component</li>
</ul>
<h2>each</h2>
<ul>
  <li>each1</li>
  <li>each2</li>
</ul>
</body>
</html>

 

まとめ

 

Bladeテンプレートにはいろいろな機能がありすぎて慣れるのに時間がかかるかもしれませんが、少しずつ使いながら覚えて行けるといいと思いました。

Bladeテンプレートについてのまとめは以下の通り。

 

  • 表示用のファイルはresources/views内に作る
  • ルーティングやコントローラからはview関数で呼び出す
  • 条件分岐や繰り返しは特別な書き方ができる
  • 表示ファイルは継承やサブビューを利用して、共通部分を分割して作ることができる

 

最後に…   Laravelをもっと勉強したいなら以下の本がおすすめです。