こんにちは。エンジニアのたべたつです。
弊社では開発のほとんどでLaravelを使用しています。LaravelはデフォルトではテンプレートはBladeが使われます。
Bladeでは以下のようにレイアウトで枠組みを作成して、個別の画面ではextendsディレクティブを用いて内容を流し込んで使うことができます
layout.blade.php
@yield('content')
index.blade.php
@extends('layout')
@section('content')
<div>hoge</div>
@endsection
sectionを使った時の問題点
とても便利な仕組みですが、1つ問題があり、読み込む側のファイルでsectionの実装を忘れてしまった際に気がつくことができません。以下のように実装をしてもエラーになりません。
index.blade.php
@extends('layout')
<!-- 実装を忘れてしまった -->
実装をし忘れても、ブラウザに表示されるので気が付けるだろう、と思うかもしれませんが、メタタグなどブラウザに直接表示されない項目の場合、開発者ツールでHTMLを覗き込まないといけません。(もしくは、リリース後にメタタグがない、と誰かに指摘されてようやく気がつきます)
解決法
hasSection、もしくはsectionMissingディレクティブの中で例外をスローする方法で事前に実装忘れを回避できます。
layout.blade.php
@hasSection('meta')
@yield('meta')
@else
@php
throw new Exception()
@endphp
@endif
もしくは
@sectionMissing('meta')
@php
throw new Exception()
@endphp
@endif
しかし、これでは表示される例外のメッセージが情報不足で、開発者は困惑してしまいますので $this->lastCompiled から対象のbladeファイルを取り出してあげることでエラーメッセージをいい感じにすることができます。
layout.blade.php
throw new Exception(array_shift($this->lastCompiled) . ' does not have "meta" section')
おわりに
ここまで書いて、振り返ったら仕組みとしてはテンプレートメソッドパターンと同じであることに気がついたので、カスタムディレクティブとテンプレートメソッドパターンを用いて、よりviewを見通しよくする方法を次回実践してみたいと思います。