速習Larave3(その4)、メッセージとビュー・コンポーサー

タグ: Laravel3  

今回はメッセージを出力するコーディングです。

ソース:github

あれ、エラーメッセージなら出力したじゃないと思っている方もいらっしゃるでしょう。そうですね。バリディーションエラーをその項目の近くで表示するコードは入れました。

今回は、もうちょっと全体的なエラーやメッセージ、例えば無事にレコードを追加しましたよというメッセージを表示できるようにします。

なにせ、前回は記事を追加しても、何も表示しないタカピーな仕様になっていました。ユーザーを惑わせてはいけません。あなたの上司、もしくは部下に何も報告、連絡しない人がいる方ならよく分かるでしょう。何も分からないあの不安をユーザーに味あわせることになります。

まずはビューにメッセージを表示できるようにしましょう。メッセージの出力は、どのページでも行えたほうが便利です。ですから、レイアウト(テンプレート)に入れましょう。

template.blade.phpでした。(今回からは、何度か編集したファイルは、フォルダーの場所を表示しません。フォルダー構成を覚えてもらうためです。もちろん、同名のファイルが存在する場合はヒントを入れておきます。)

<!doctype html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>@yield('title')</title>
    <meta name="viewport" content="width=device-width">
    {{ HTML::style('laravel/css/style.css') }}
</head>
<body>
    <div class="wrapper">
        <header>
            <h1>ミニブログ</h1>
            <h2>@yield('title')</h2>
            <p class="intro-text" style="margin-top: 45px;">
            </p>
        </header>
        <div>
            @if ( $warning )
                <div style="color: red;">
                    {{ $warning }}
                </div>
            @endif
            @if ( $message )
                <div style="color: green;">
                    {{ $message }}
                </div>
            @endif
        </div>
        <div role="main" class="main">
            <div class="home">
                @yield('content')
            </div>
        </div>
    </div>
</body>
</html>

$warning$messageという変数があれば、表示色を変え表示します。今回のチュートリアルではCSSをいじらず、コーディングに集中するため、styleで指定しています。

ビューに変数で渡すためにはview('ビュー名')->with('ビューで使用する変数名', 渡したい内容)でした。すると全ビューの出力で以下のようなコードを入れる必要があるわけです。

return view('ビュー名')
    ->with('message', $message)
    ->with('warning', $warning);

いや。ちょっと待ってください。これは、ビューを表示するルート中で直接指定しているだけです。実際、メッセージを指定したい状況は、フォームの送信内容を処理するルートから指定したい場合のほうで需要が多いはずです。ビューの表示ルートへのリダイレクトを送信する側です。

Laravelには用意されています。まず次のコードを見てください。

return Redirect::to_route('ルート名')
    ->with('message', $message)
    ->with('warning' $warning);

あれ、ビューに変数を渡すのと同じようなコードですね。ええ。リダイレクトにwith()を使用できるんです。

実際にリダイレクトするのはブラウザです。ブラウザに対して、どこのURLへ移動してくださいとお願いするのがリダイレクトです。ですからリダイレクト先はリダイレクト元とは別のページリクエストです。Webのアクセスは前回の接続の情報を引き継ぎません。難しい言葉で言えば「ステートレス」、状態不保持になります。

それでは不便なので、ブラウザに情報を残すクッキーが付け加えられました。ただ、クッキーには大きさの制限があります。また、ユーザーのブラウザに保存されるため、そのユーザーが悪い人であったり、コンピューターがウィルスに汚染されていると、いたずらされる可能性があります。

そこで、前回の情報を引き継ぐ仕組みとして、セッションが考えだされました。リダイレクトに対してwith()を使用すると、このセッションに保存されます。

これで、リダイレクト元がどこであろうと、リダイレクト先のビューにメッセージを届けられるわけです。ビューの表示直前のコードはこうなります。

$warning = isset($warning) ? $warning : Session::get('warning', false);
$message = isset($message) ? $message : Session::get('message', false);
return view('ビュー名')
    ->with('message', $message)
    ->with('warning', $warning);

このコードの直前で既に$message/$warningが指定されている場合は、それを優先してセットします。まだ指定されていない場合はセッションに保存されている情報を取り込みます。セッションに存在していない場合はfalseを返します。

やれやれ、これで上手く行きそうです。さて、全ビューの呼び出しをこれに変えましょう…うーん。嫌ですね。毎回同じ事を繰り返すのは。メソッドを使ってまとめる?

いいえ。Laravelにはもっと良い方法が用意されています。あるビューに対する出力を準備するためのコードを指定できるんです。

すると、出力ビュー全部に対して指定するんでしょうか?それだと、手間はかえって増えそうですね。

いいえ。全ページで共通して出力されるビューがあるじゃありませんか。レイアウトです。レイアウトのビューに対して、この方法を使用すれば、一つコードを追加するだけで、全出力ページにエラーメッセージを用意してくれることになります。

この仕組みをビュー・コンポーサーと言います。早速コーディングしてみましょう。routes.phpへ追加します。

参照:ビュー・コンポーサー

View::composer('template',
    function($view) {
        $view->warning = isset($view->warning) ? $view->warning : Session::get('warning', false);
        $view->message = isset($view->message) ? $view->message : Session::get('message', false);
    });

templateビューに対してコンポーサーを指定します。無名関数にはビューが渡ってきます。もし、ビューに対しwith()で値を渡された場合、そのビューインスタンスのプロパティとして渡ってきます。

それが存在していれば、その値のまま、もし未設定ならば、セッションからデーターを探し、渡します。セッションにも無ければfalseになります。このコードで必ず$warningと$messageは用意されますので、ビューではif文に変数名だけでチェックできます。コードが単純になりますからね。

では、これを使って早速改造しましょう。不親切だった、新しい記事を追加した時に何もユーザーに伝えていなかった点を改良します。

routes.phpです。既にコードは理解されているでしょうから、変更点だけ紹介しますね。

            // 続けて追加できるように、
            // フォームは空のままリダイレクト
            return Redirect::to_route('post-add')
                    ->with('message', '記事を追加しました。');

一行目のコメントも分かりやすく変えました。二行目は変わっていないので、どこか迷った時の目印にしてください。

with()で表示したいメッセージを渡しているだけです。記事を追加後に緑色でメッセージが表示されることを確認してください。