見えないViewの実装忘れを防ぐ

こんにちは。エンジニアのたべたつです。

弊社では開発のほとんどで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を見通しよくする方法を次回実践してみたいと思います。