Laravel歴1ヶ月のど素人です。
DBから取得した結果をviewに共通の変数として渡したいって時にどうしたらいいのか、
公式を参考に作ってみました。
とりあえず公式を参考に作ってみる
Laravel公式はこちら
https://readouble.com/laravel/8.x/ja/views.html
ComposerServiceProvider
namespace App\Providers;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
public function register()
{
}
public function boot()
{
View::composer(
'*', 'App\Http\View\Composers\CategoryComposer'
);
}
}
自前で作ったComposerクラス
namespace App\Http\View\Composers;
use App\Repositories\Category\CategoryRepository;
use Illuminate\View\View;
class CategoryComposer
{
protected CategoryRepository $category;
public function __construct(CategoryRepository $category)
{
$this->category = $category;
}
public function compose(View $view)
{
// DBからデータを取得してビューに渡す
$view->with('category_groups', $this->category->getCategoryGroupList());
}
}
このままサイトを表示すると・・・
N+1を検知するライブラリを仕込んでいたので、全ページで上記のアラートが出るように。。。
おそらくサイト全体のviewをパーツ化し読み込んでいるので、そのパーツをレンダリングするたびにSQLが実行されてしまっているようでした。
また、以下のQiitaを参考に実装をしてみましたが、「middlewareの仕事じゃない!」とコードレビューで指摘を受けてしまい。。。。
シングルトンにすることでSQL実行を一回に
こんな感じにすることで、同じ処理が何度も呼ばれることは無くなりました。
ComposerServiceProviderを修正
namespace App\Providers;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
public function register()
{
// 自前で作ったCategoryComposerをシングルトンに登録する
$this->app->singleton(\App\Http\View\Composers\CategoryComposer::class);
}
public function boot()
{
View::composer(
'*', 'App\Http\View\Composers\CategoryComposer'
);
}
}
自前で作ったComposerクラスをすこし改良
namespace App\Http\View\Composers;
use App\Repositories\Category\CategoryRepository;
use Illuminate\View\View;
class CategoryComposer
{
protected $category_group;
public function __construct(CategoryRepository $category)
{
// DBから取得した結果をプライベート変数に保存しておく
$this->category_group = $category->getCategoryGroupList();
}
public function compose(View $view)
{
// 何度呼ばれてもコンストラクタで取得しておいた結果を返すようにする
$view->with('category_groups', $this->category_group);
}
}
おわり
ググり方が悪かったのか、なかなか解決できなかったのでqiita記事にしてみました。
別の方法が何かあればコメントもらえると嬉しいです。