viewに渡すこの変数いろんなところで使ってて、それぞれのメソッドで返してるのめんどくさいなぁ
サイドバーとか全ページに共通するデータは1つにまとめたいなぁ
こんなこと思ったことないですか?
Laravelを使っていてそんな時に便利なのがViewComposerです。
共通のデータを1箇所でまとめたい時に調べて出てきたのでViewComposerについてまとめます。
ViewComposerとは
ビューをレンダリングする時に呼び出される、コールバックかクラスメソッドのことです。
要は、変数などビュー表示のためのビジネスロジックを書くところです。
ビューにはできるだけロジックを書きたくないのでそういった時に役立ちます。
こんな感じ↓
ViewComposerの実装方法
今回はサイドバーにユーザー情報を表示するという例で進めます。
- ViewComposer用のサービスプロバイダー作成
- app.phpにプロバイダーを登録
- データをビューと結合させるためのComposerクラスを作成
- 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はレンダー前、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を使用した方が無難かもしれません。
コメント