【Laravel】ViewComposerを使って共通の値をViewに渡そう!

Laravel ViewComposerプログラミング

viewに渡すこの変数いろんなところで使ってて、それぞれのメソッドで返してるのめんどくさいなぁ

サイドバーとか全ページに共通するデータは1つにまとめたいなぁ

こんなこと思ったことないですか?

Laravelを使っていてそんな時に便利なのがViewComposerです。

共通のデータを1箇所でまとめたい時に調べて出てきたのでViewComposerについてまとめます。

ViewComposerとは

ビューをレンダリングする時に呼び出される、コールバックかクラスメソッドのことです。
要は、変数などビュー表示のためのビジネスロジックを書くところです。

ビューにはできるだけロジックを書きたくないのでそういった時に役立ちます。

こんな感じ↓

ViewComposerの実装方法

今回はサイドバーにユーザー情報を表示するという例で進めます。

  1. ViewComposer用のサービスプロバイダー作成
  2. app.phpにプロバイダーを登録
  3. データをビューと結合させるためのComposerクラスを作成
  4. 1で作成したサービスプロバイダーへの設定

1. ViewComposer用のサービスプロバイダー作成

php artisan make:provider ViewServiceProvider
<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ViewServiceProvider extends ServiceProvider
{
    /**
     * 全アプリケーションサービスの登録
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * 全アプリケーションサービスの初期起動
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

2. app.phpにプロバイダーを登録

<?php

return [
    // 省略
    'providers' => [
        App\Providers\ViewServiceProvider::class,  <= 追加
    ],
];

3. データをビューと結合させるためのComposerクラスを作成

app/Http/ViewComposersというディレクトリを作成します。(ディレクトリ名は何でも良い)

その中にUserComposer.phpを作成します。

<?php

namespace App\Http\View\Composers;

use App\Repositories\UserRepository;
use Illuminate\View\View;

class UserComposer
{
    /**
     * userリポジトリの実装
     *
     * @var UserRepository
     */
    protected $user;

    /**
     * @param  UserRepository  $user
     * @return void
     */
    public function __construct(UserRepository $user)
    {
        // 依存はサービスコンテナにより自動的に解決される
        $this->user = $user;
    }

    /**
     * データをビューと結合
     *
     * @param  View  $view
     * @return void
     */
    public function compose(View $view)
    {
        $user = $this->user->getUser();
        $view->with('user', $user);
    }
}

userという変数に$this->user->getUser()で取得したユーザー情報が渡されます。

ビューがレンダーされる直前に、Illuminate\View\Viewインスタンスに対しコンポーザのcomposeメソッドが呼びだされます。

4. 1で作成したサービスプロバイダーへの設定

<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ViewServiceProvider extends ServiceProvider
{
    /**
     * 全アプリケーションサービスの登録
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * 全アプリケーションサービスの初期起動
     *
     * @return void
     */
    public function boot()
    {
        // クラスベースのコンポーザを使用する
        View::composer(
            'user', 'App\Http\ViewComposers\UserComposer'
        );

        // その他の指定方法↓
        // クロージャベースのコンポーザを使用する
        View::composer('user', function ($view) {
            //
        });
        // まとめて指定も可
        View::composers([
            App\Http\ViewComposers\UserComposer => 'user',
            App\Http\ViewComposers\CompanyComposer => 'companies.*',
            App\Http\ViewComposers\UserComposer => 'layouts.app',
        ]);
    }
}

上記によりUserComposerのcomposeメソッドが呼び出されuser.blade.phpで$userという変数が利用できます。

ビューにバインドされたコンポーザーを呼び出すイメージですね。

複数のビューに適応させたい時

View::composer(
    ['user', 'top'],
    'App\Http\ViewComposers\UserComposer'
);

全ビューに対して適応させたい時

View::composer(
    *,
    'App\Http\ViewComposers\UserComposer'
);

気をつけた方がいいと思う点

例えばサイドバーなど全ビューで利用するためのViewComposerを作成した場合、そのViewComposerはページ読み込み時に毎回実行されるためクエリが毎回走ります。

Eagerローディングされてないロジックを呼び出す場合などは毎回すごい量のクエリが実行されるので悲惨です。

ViewComposerは便利ですが、複雑なロジックの場合は使用するべきか考える必要はありそうです。

View::composerとView::creatorの違い

View::composerに似たメソッドでView::creatorというメソッドがあります。

基本的に動作は一緒なのですが、実行されるタイミングが異なります。

creatorはviewインスタンスが作成されるとすぐに実行されます。

composerはviewインスタンスからviewがコンパイル、結合されて文字列に変換されるときに実行されます。

イメージとしてはcreatorはレンダー前、composerはレンダー後ですね。

実際の動きを見てみるとわかりやすいです。

View::creator('layout', function($view) {
    $view->with('foo', 'bar');
});

// コントローラー内
return View::make('layout')->with('foo', 'hogehoge');

ビューではhogehogeと定義されます。

コントローラーで上書きされているわけですね。

View::composer('hello', function($view) {
    $view->with('foo', 'bar');
});

// コントローラー内
return View::make('hello')->with('foo', 'hogehoge');

ビューではbarと定義されます。

コントローラーでは上書きされずコンポーザーで定義したものがそのままビューに定義されます。

参考:Difference between View Composer and Creator in Laravel? | stackoverflow

こういった挙動になるため特別な理由がない限りはcomposerを使用した方が無難かもしれません。

ビュー 7.x Laravel

コメント

タイトルとURLをコピーしました