九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、僕がLaravelを使い始めてからかれこれ2年ぐらいが経とうとしていますけど、今でもLaravelの開発は活発に行われていて、たった半年過ぎただけでもっと便利な使い方ができるようになってたりします。
それは、Laravelのテンプレート・エンジン「Blade」でも同じなんで、ここいらできっちりBladeの基本機能をまとめておくことにしました。
みなさんの参考になれば嬉しいです。
※新年度ということで、新社会人を想定した文章にしてます。なので、少し回りくどい表現があるかもしれません。(新社会人さん!努力が100%報われるとは思いませんが、プログラム面白いんでやってみる価値はあると思います♪ぜひ楽しくできるよう、工夫していってください。m_ _m)
目次
1.テンプレートの読み込み
まずは基本中の基本、テンプレートファイル(HTMLタグとかが含まれているファイル)の読み込みです。
やり方はシンプルで、コントローラーで、
public function index() { return view('home'); }
というように、view()の中で指定するだけでOKです。
気をつけなければいけないのは、この場合読み込まれるテンプレートファイルが、
/resources/views/home.blade.php
という点です。実際には「.blade.php」が省略されてるわけですね。
そして、もし
/resources/views/user/home.blade.php
というように、一階層下のフォルダにテンプレート・ファイルがある場合は、
public function index() { return view('user.home'); }
という具合に、ドットでつないで指定します。
2.データの表示
これも基本のデータ表示(呼び出し)です。
Bladeの中で変数の中身を表示したい場合は、
{{ $test }}
とします。
ひげ括弧はキーボードでいうと、エンターキーの近くにある文字です。Shiftボタンを押しながら押します。
そして、$testを使えるようにするには、コントローラーで、view()の2つ目に配列としてセットしてやりましょう。
public function index() { return view('home', [ 'test' => 'テストは嫌いだ' ]); }
ここで注意が必要なのは、セットする配列には、$(ドルマーク)は含まれてないですけど、呼び出すときは「$」が必要というところです。
また、Bladeのひげ括弧は、自動で「”」を「"」など安全な文字に変換してくれるようになっていますが、たまにそのまま表示してほしい場合もあったりします。
その場合は、
{!! $test !!}
を使えばそのままで表示させることができます。
ちなみに、次のように「or」を使うと、デフォルトの文字列を指定することができます。
{{ $name or '太郎' }}
つまり、もし「$name」が見つからない場合は、「太郎」が表示され、もし「二郎」がセットされていれば「二郎」が表示されることになります。
public function index() { return view('home', [ 'name' => '二郎', ]); }
3.if文
Bladeでは、PHPのように「if」文を使うことができます。
使い方はこんな感じです。
@if ($number == 1) 1 @elseif ($number == 2) 2 @else その他 @endif
PHPとほとんど同じなので問題はないと思います。
ちなみに、Bladeにはif文に似た、以下のようなものもあります。
@unless
ifの否定バージョンです。
つまり、次の例は「ログインしてない」なら「ログインしてね!」が表示されます。
@unless (auth()->check()) ログインしてね! @endunless
@isset
issetは、データが存在してるかどうかです。これもPHPと同じですね。
@isset($numbers) あります! @endisset
※注意が必要なのは、データが「存在してるかどうか」という点です。つまり、コントローラーで、以下のようにからの変数が指定されている場合は「存在してる」ということになって、「あります!」が表示されてしまいます。
return view('home', [ 'numbers' => [] ]);
@empty
emptyもPHP関数と同じく、データが空(存在してない)場合に表示されます。
@empty($numbers) 空だね! @endempty
@auth
ログインしてるかどうかを判別できます。
@auth ログイン中! @endauth
4.ループ
@ifと同じく、PHPの「for()」や「foreach()」のようにたくさんのデータをループで回しながら表示をすることができます。
@for
たとえば、
@for ($i = 0; $i < 10; $i++) $i の中身は、 {{ $i }}<br> @endfor
とすると、
$i の中身は、 0 $i の中身は、 1 $i の中身は、 2 $i の中身は、 3 $i の中身は、 4 $i の中身は、 5 $i の中身は、 6 $i の中身は、 7 $i の中身は、 8 $i の中身は、 9
と表示されます。
@foreach
また、コントローラーでデータをセットして、
public function index() { return view('home', [ 'numbers' => [1,2,3,4,5] ]); }
@foreach ($numbers as $number) <p>$numberの中身は、 {{ $number }}</p> @endforeach
とすると、
$numberの中身は、 1 $numberの中身は、 2 $numberの中身は、 3 $numberの中身は、 4 $numberの中身は、 5
と表示させることができます。
@forelse/@empty
そして、phpにはないBlade独自の書き方なのが、「@forelse〜@empty〜@endforelse」です。
これは、変数が空だったときに@emptyが表示されるようになる便利な書き方です。さっきの例で言うと、以下のようになりますが、もし$numbersが空場合は「数字なし」が表示されます。
@forelse ($numbers as $number) {{ $number }} @empty <p>数字なし</p> @endforelse
※ただし、$numbersの中身がnullの場合や、変数そのものがコントローラーで指定されていない場合はエラーが出るので注意してください。
※また、phpと同じく@whileもありますけど、あれは場合によってはヤバイので省略します(笑)
そして、ループで忘れては行けないのが「$loop」です。@foreachや@forelseを使うと自動的に変数「$loop」が使えるようになって、ここからいろいろとデータを取り出すことができます。
実際の例はこんな感じです。
@foreach ($numbers as $number) ・0から始まる番号、{{ $loop->index }}<br> ・1から始まる番号、{{ $loop->iteration }}<br> ・残りは、{{ $loop->remaining }} 個<br> ・データ数は、{{ $loop->count }}<br> @if($loop->first) ・最初のデータは、{{ $number }}<br> @elseif($loop->last) ・最後のデータは、{{ $number }}<br> @endif @endforeach
@each
もし、他のテンプレートを呼び出してループをしたい場合は「@each」が便利です。
たとえば、「/resources/partials/section.blade.php」に次のようにしておいて、
<li>{{ $name }}</li>
こんな感じで呼び出すと、全ての部署名が<li></li>で囲まれて表示されます。
@each('partials.section', $sections, 'name')
※注意する場所は、@eachの3つ目のデータです。ここがsection.blade.phpの「$name」に対応しています。
5.テンプレートの継承(共通部分をつくる)
テンプレートがページごとに必要となったらファイルだらけになってしまいますし、そうなると、共通部分もことあるごとに変更しなければいけません。
そんなときに役にたつのが、継承です。
次のようなページを見てみましょう。
はい。ページ上部のヘッダーは全く同じで、テキストだけが違ってますね。
この場合、テンプレートは、
- 共通部分(レイアウト)
- ページ部分(1つ目のページ、2つ目のページ)
に分けて作成します。
こうしておくことで、もし3つ目のページが必要になっても4つ目のページが必要でも共通部分はひとつのファイルだけで管理することができます。
では、やり方です。
まず共通部分(レイアウト)を作成しましょう。
フォルダはどこでもいいですけど、Laravel的には、「/resources/views/layouts」の中となっています。この中には、app.blade.phpというファイルがあると思いますけど、練習ですので、「main.blade.php」という新しいファイルを作成します。
(main.blade.php)
<html> <head></head> <body> <h1>ここは共通</h1> </body> </html>
※ホントはmataタグとかがあったほうがいいですけど、練習なのでシンプルにしてます。
そして、この共通部分にページごとに違う内容を表示したい場合は、@yield()を使います。(あとで、ここがページ部分に置きかえられます)
<html> <head></head> <body> <h1>ここは共通</h1> @yield('content') </body> </html>
※contentという名前は自分の好きなものでOKです。
では、ページごとのテンプレートを作っていきましょう。
これもどこでもOKですが、「home」ファルダなどにまとめておくと管理しやすいと思います。
- /resources/home/one.blade.php
- /resources/home/two.blade.php
中身はこんなカンジです。
@extends('layouts.main') @section('content') 1つめのページ @endsection
最初の@extendsがさっき作った共通部分のテンプレートの、
/resources/layouts/main.blade.php
を読み込んでいます。
そして、@section(‘content’)〜@endsectionまでが、さっきの@yield(‘content’)と置き換えられることになるわけです。
つまり表示されるのは、
<html> <head></head> <body> <h1>ここは共通</h1> 1つめのページ </body> </html>
となるわけですね。そして、2つ目のページも同じで、two.blade.phpに、
@extends('layouts.main') @section('content') 2つめのページ @endsection
とすればOKです。
そして、@sectionはどこにでも作っていいので、共通部分を次のようにすれば、特定のページだけで、CSSファイルやJavaScriptファイルを読みこむこともできるようになりますし、タイトルもページごとに変更できます。
<html> <head> <title>@yield('title')</title> @yield('style') </head> <body> <h1>ここは共通</h1> @yield('content') @yield('script') </body> </html>
この場合、ページごとのファイルはこんな感じになります。
@extends('layouts.main') @section('title') 1つ目のタイトル @endsection @section('content') 1つ目のページ @endsection @section('script') <script src="/js/***.js"></script> @endsection @section('style') <link rel="stylesheet" href="/css/***.css"> @endsection
※ちなみに、内容が短い場合は、
@section('title', 'タイトル')
という使い方もできるので、状況に合わせて使い分けるのもいいかもしれません。
@parent
もし、共通部分(親テンプレート)の上下に何かを表示したい場合は、@section()〜@showを作っておいて、
<html> <head></head> <body> <h1>ここは共通</h1> @section('sidebar') サイドバー @show </body> </html>
ページごとのファイル内で、
@section('sidebar') <p>サイドバーの上</p> @parent <p>サイドバーの下</p> @endsection
という風に、@parentを使えば親テンプレート内の上下にコンテンツをつくることができます。
※これをやっておくと、もし、@section(‘sidebar’)〜@endsectionがない場合、「サイドバー」だけが表示されることになるので、ユーザーごとに情報を切り替えたい場合に使いやすいかもしれません。
6.サブ・ビュー(使い回し部分:その1)
例えば、bootstrapのbadgeのように、何回も使う部分を共通化しておけば変更があったとき、このファイルを変更するだけでいいので便利です。
そんな場合に役立つのが一部分だけを別のテンプレートから呼び出すことができる機能「サブ・ビュー」です。
実際の例を見てみましょう。
まず、一部分だけのテンプレートファイルを作成します。
/resources/views/partials/section.blade.php
<span class="badge badge-primary">営業部</span>
そして、呼び出したい場所で
@include('partials.section')
とするだけでOKです。
もし、可変にしたい場合は、部分ファイルで変数を表示するようにして、
<span class="badge badge-{{ $type }}">{{ $name }}</span>
呼び出し元で、変数を設定してあげましょう。
@include('partials.label', [ 'type' => 'success', 'name' => '営業部' ])
この例だと、以下のようになります。
<span class="badge badge-success">営業部</span>
7.コンポーネント(使い回し部分:その2)
一部分を表示するには、サブ・ビューでもできますが、Bladeではもうひとつコンポーネントというやり方も用意されています。
基本的なやり方は、サブ・ビューと同じで、部分テンプレートを作成し、
/resources/components/alert.blade.php
<div class="alert alert-danger"> {{ $slot }} </div>
@component を使って呼び出すだけです。
@component('components.alert') <strong>エラー!</strong><br> ログイン情報が間違っています。 @endcomponent
サブ・ビューと違うのは「スロット」を使ってデータを表示するところです。もし、個別のスロットを指定したい場合は、呼び出す場所で次のように@slot(‘****’)を使います。
@component('components.alert') @slot('title') 警告! @endslot ログイン情報が間違っています。 @endcomponent
この場合、呼び出される「部分ファイル」にはスロット名に対応する「$title」を指定します。
<div class="alert alert-danger"> <div class="alert-title">{{ $title }}</div> {{ $slot }} </div>
そして、結果は以下のようになります。
<div class="alert alert-danger"> <div class="alert-title">警告!</div> ログイン情報が間違っています。 </div>
つまり、アラートのタイトルを可変にすることができるわけですね。
ちなみに、個人的にはサブ・ビューの方がシンプルで好きですが、コンポーネントの魅力の一つとして、独自の名前で呼び出すことができるようになる点があります。(つまり、@alert()で呼び出しができる)
やり方は、「/app/Providers/AppServiceProvider.php」というファイルのboot()内で以下のように登録しておくだけです。
public function boot() { \Blade::component('components.alert', 'alert'); }
※「components.alert」がファイルの場所です。
これで、@alert()〜@endalert が使えるようになります。
@alert(['title' => '警告!']) ログイン情報が間違っています。 @endalert
※なので、モーダルを作る場合とかに重宝するかもしれません。
8.配列をjsonに変換
配列をjsonに変換する場合は、PHP関数のjson_encode()を使いますけど、Bladeには@jsonという書き方があってよりシンプルに書くことができます。
(コントローラー)
public function index() { return view('home', [ 'sections' => ['営業部', '総務部', '企画部', '人事部'] ]); }
(テンプレート)
var numbers = @json($sections);
結果は、
var numbers = ["\u55b6\u696d\u90e8","\u7dcf\u52d9\u90e8","\u4f01\u753b\u90e8","\u4eba\u4e8b\u90e8"];
となります。JavaScriptとの連携にいいかもしれません。
ちなみに、Laravelの「コレクション」は、データを自動でjson形式にしてくれるので、こちらも覚えておくと便利かもしれません。
public function index() { return view('home', [ 'sections' => collect(['営業部', '総務部', '企画部', '人事部']) ]); }
var numbers = {!! $sections !!};
※ただし、エスケープされてしまうので、{!! *** !!}で、エスケープしない表示の仕方にする必要があります。
9.{{}}ひげ括弧をそのまま表示する
Vue.jsなどは、Bladeと同じく、以下のようにひげ括弧を使って変数を表示します。
<div>{{ test }}</div>
ただ、このままだとBladeがひげ括弧内を変換してしまうので連携がうまくいかなくなってしまいます。
そこで、登場するのが@{{ **** }} です。
以下のようにすると、ひげ括弧が変換されず、そのまま表示させることができます。
<div>@{{ test }}</div>
表示結果は、次のようになります。
<div>{{ test }}</div>
※ちなみに、こういうことが発生するので、僕の場合、vue.jsでは、「v-text」もしくは「v-html」を使ってデータ表示するようにしています。
<div v-text="test"></div> <div v-html="test"></div>
10.PHPコードを書きたい
Bladeの中でもPHPのコードを書きたいときがたまにあったりします。
その場合は、@php〜@endphpを使いましょう。
@php echo 'PHPコードで表示してます。'; @endphp
11.独自の命令文を作りたい
Bladeは、@*****という形で独自のコード呼び出しができるようになっています。
例えば、@datetimeを作っておいて実行すると、
@datetime(now())
以下のように、日本の日付形式に変換してくれたら便利ですよね。
2018年04月04日 05:23
これを実現するには、「/app/Providers/AppServiceProvider.php」のboot()内に以下のような記述をします。
public function boot() { \Blade::directive('datetime', function ($expression) { return "<?php echo ($expression)->format('Y年m月d日 H:i'); ?>"; }); }
ここで注意が必要なのは、return の中身がPHPコードになっているという部分です。正直な所、ここはもっとシンプルに出来るんじゃないか?と思ってるんですけど、現状はこの書き方をする必要があります。
独自のif文
さらに、Bladeは「独自のif文」も作成することができます。
例えば、今日が映画館で水曜日だと「レディースデー」で入場料が安い場合がありますが、これを実装してみましょう。
まず、同じように「/app/Providers/AppServiceProvider.php」のboot()内に以下のような記述をします。
\Blade::if('discount', function ($week_day) { return ($week_day == 3); // 3は水曜日 });
そして、テンプレートで以下のように呼び出して下さい。
@discount(date('w')) 今日は1,000円 @else 今日は1,800円 @enddiscount
ということで、今回はBladeをまとめてみました。
ぜひみなさんも便利な書き方を覚えて楽にコードを書いていきましょう!
ではでは〜。