Laravelでのルーティングからビューにデータを渡すまで

Laravel

Laravelにおけるルーティングからビューにデータを渡すまでの基本的な実装パターンをまとめました。状況に応じて適切なパターンを使い分けましょう。

ルーティング

クロージャによるルーティングはいたって単純です。

Route::get('/', function () {
    return view('welcome');
});

ルーティングにクロージャを使用すると、ルートキャッシュは動作しません。ルートキャッシュを使用するには、コントローラルートを定義します。

Route::get('/user', 'UserController@index');

ビュールート

ルートからビューを返すだけの場合は、Route::viewメソッドを使用します。このメソッドを使用しても、ルートキャッシュは動作するようです。

Route::view('/welcome', 'welcome');

ビューにデータを渡す

viewヘルパ関数を使用して、データを配列でビューに渡せます。

Route::get('/', function () {
    return view('greeting', ['name' => 'James']);
});

withメソッドでビューに渡すデータを個別に追加することもできます。

Route::get('/', function () {
    return view('greeting')->with('name', 'Victoria');
});

ビュールートでデータを渡す

Route::viewメソッドでは、ビューへ渡すデータの配列を第3引数として指定します。

Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

ここで、allgetのようなメソッドでモデルを取得して渡すのは避けるべきです。モデルはクロージャやコントローラの中で取得しないと、該当ルート以外のリクエストでも、routes/web.phpファイルが読み込まれる毎にクエリが実行されてしまいます。また、場合によってはユニットテストでIlluminate\Database\QueryException例外が投げられることがあります。

Route::view('/', 'welcome', ['categories' => Category::all()]);
1) Tests\Feature\ExampleTest::testBasicTest
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1 no such table: categories (SQL: select * from "categories")

これはテスト実行時、マイグレーションが実行される前に、routes/web.phpファイルが読み込まれることが原因です。

全ビュー間のデータ共有

アプリケーションの全ビューでデータを共有するには、View::shareメソッドを使います。

View::share('key', 'value');

通常、サービスプロバイダのbootメソッド内で呼び出しますが、ここでもモデルを取得して渡していると、先ほどの例と同様にエラーの原因になります。

参考
QueryException: General error: 1 no such table: {table_name} (SQL: select * from “{table_name}”) · Issue #27018 · laravel/framework

ビューコンポーザ

ビューコンポーザは、ビューがレンダーされる直前に呼び出されます。したがって、ビューにモデルを渡す場合にも使えます。

View::composer('welcome', function ($view) {
    $categories = Category::all();
    $view->with('categories', $categories);
});

ビューコンポーザを複数のビューに適用するには、View::composerメソッドの最初の引数を配列で渡します。

View::composer(['welcome', 'home'], function ($view) {
    //
});

composerメソッドに渡しているビュー名には、ワイルドカードとして*を使用することもできます。

View::composer('*', function ($view) {
    //
});

Laravelにおける存在チェックの書き方

Laravel

Laravelでビューに渡されたEloquentコレクションの中身が存在しているか判別するプログラムの書き方をまとめます。

データをビューへ渡す

まず、データを表示するためにEloquentでコレクションを取得してビューへ渡します。

public function index()
{
    $users = User::all();

    return view('users', ['users' => $users]);
}

単にデータを表示する

ビューに渡されたデータはループで表示できます。

<html>
    <body>
        <h1>User</h1>

        @foreach($users as $user)
            <p>{{ $user->name }}</p>
        @endforeach
    </body>
</html>

データの存在を判別する

データの存在を判別するには、isNotEmptyメソッドを使います。

<html>
    <body>
        <h1>User</h1>

        @if ($users->isNotEmpty())
            <ul>
                @foreach($users as $user)
                    <li>{{ $user->name }}</li>
                @endforeach
            </ul>
        @else
            Nothing Found
        @endif
    </body>
</html>

逆の動作である、isEmptyメソッドを使うこともできます。

<html>
    <body>
        <h1>User</h1>

        @if ($users->isEmpty())
            Nothing Found
        @else
            <ul>
                @foreach($users as $user)
                    <li>{{ $user->name }}</li>
                @endforeach
            </ul>
        @endif
    </body>
</html>

その他の判別方法

より単純なケースでは、@forelse()が使えるかもしれません。

<html>
    <body>
        <h1>User</h1>

        @forelse($users as $user)
            <p>{{ $user->name }}</p>
        @empty
            Nothing Found
        @endforelse
    </body>
</html>

ちなみに、以下のような書き方では@empty()がうまく判別できませんでした。

<html>
    <body>
        <h1>User</h1>

        @foreach($users as $user)
            <p>{{ $user->name }}</p>
        @endforeach
        @empty($users)
            Nothing Found
        @endempty
    </body>
</html>

リレーションの存在の判定

リレーションの有無を調べるには、existsメソッドとdoesntExistメソッドが使用できます。

<html>
    <body>
        <h1>User</h1>

        @if ($user->posts()->exists())
            The user has some posts
        @endif

        @if ($user->posts()->doesntExist())
            The user doesn't have any posts
        @endif
    </body>
</html>