はじめに
こちらは筆者がLaravelに関する知識の定着を図るための投稿です。
以下の点にご注意ください
- この記事の読者は新人PGの方や私と同じ三流PGの方を想定しています
- 記事内において間違いや冗長な説明が多々あることをご容赦ください
- 公式ドキュメントと相違がある場合はそちらを参考にしてください
- 公の場で記事を引用していただく場合は予めご連絡ください
- コメント大歓迎です!!出来るだけ返信しようと思っております!!
今回のテーマ
Laravelで各ページを表示する際に同じ変数を共有して画面表示する方法を調べました。
今回は以下の3つの方法を紹介します。
- View::share()を利用する
- View::composer()を利用する
- ミドルウェアを利用する
想定している読者
- 各画面の共通部分にデータベースから取得した情報を表示したい人
- 共通して表示する情報をviewに渡す動作をcontroller上で毎回記述したくない人
- サービスプロバイダーやミドルウェアの動作を理解したい人
今回はLaravel 11で実装しています。他バージョンでの実装時は公式ドキュメントも参照してください
1. View::share()を利用する
Laravelアプリケーションがレンダリングする全てのビューに無条件で変数を渡します。最もシンプルな方法であり、サイト名など必ず使う静的なデータに向いています。通常サービスプロバイダーのbootメソッド内で呼び出す必要があります。
サービスプロバイダーとは、簡単に言うと「アプリケーションの起動時に準備を行うクラス」です。Laravelには様々な用途のサービスプロバイダーが用意されており、今回はAppServiceProviderを利用します。
実装例
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View; // 必ずインポートする
class AppServiceProvider extends ServiceProvider
{
/**
* 全アプリケーションサービスの登録
*/
public function register(): void
{
// ...
}
/**
* 全アプリケーションサービスの初期起動
*/
public function boot(): void
{
// 'siteName' という変数名で、すべてのビューに共有します
// どのbladeファイルからでも{{ $siteName }}と書くと'My Awesome App'が画面表示
View::share('siteName', 'My AwesomeApp');
}
}
2. View::composer()を利用する
指定した特定のビューにのみ変数を渡します。サイドバーに最新記事を表示する場合やユーザーの通知一覧など、大規模なデータベースから検索して持ってくる必要があり、共通して使われる特定のビューを指定して利用します。
この方法でもAppServiceProviderを利用します。
実装例
クロージャベースの実装とクラスベースの実装があります
- クロージャベース
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View; // 必ずインポートする
class AppServiceProvider extends ServiceProvider
{
/**
* 全アプリケーションサービスの登録
*/
public function register(): void
{
// ...
}
/**
* 全アプリケーションサービスの初期起動
*/
public function boot(): void
{
// 'layouts.header' と 'layouts.footer' のビューが描画される時のみ実行されます
// 指定したビューが使われないページでは実行されません。
View::composer(['layouts.header', 'layouts.footer'], function ($view) {
$view->with('categories', ['News', 'Sports', 'Tech']);
});
// ワイルドカード '*' を使うとすべてのビューに適用することも可能ですが、
// パフォーマンスを考慮して特定のビューを指定するのが基本です。
View::composer(['user.*'], function ($view) {
$view->with('userinfo', ['ID', 'Name', 'Notice']);
});
}
}
- クラスベース
Laravelには、Composerクラス用のデフォルトディレクトリがないため、任意の場所にフォルダを作成することが出来ます。今回はApp\View\Composersを作成します。
まず、クラス用のファイルを作成します。
<?php
namespace App\View\Composers;
use Illuminate\View\View;
use App\Models\Post;
// 例としてサイドバー用にPostモデルを利用し、
// DBから最新記事を取得するSidebarComposerクラスを示します
class SidebarComposer
{
/**
* データをビューに結合します。
*/
public function compose(View $view): void
{
//
$recentPosts = Post::latest()->take(5)->get();
// 変数をビューに渡します
$view->with('recentPosts', $recentPosts);
}
}
次にサービスプロバイダーで登録します
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
use App\View\Composers\SidebarComposer; // 作成したクラスを読み込む
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
// 'layouts.sidebar'ビューが読み込まれるときのみ、{{ $recentPosts }}最新記事5件を取得できます。
View::composer('layouts.sidebar', SidebarComposer::class);
}
}
3. ミドルウェアを利用する
認証情報(ログインユーザーなど)やセッションデータに基づいた変数をすべてのビュー(または特定のルート)に共有したい場合に最適です。
先ほどのサービスプロバイダーは、アプリケーションの起動時に行う操作のため、起動後に行われるログイン・セッション処理などの情報は取得できません。一方でミドルウェアはHTTPリクエスト処理の前後で実行されるのでこれらの情報を取得することが可能です。
実装例
まず、ターミナルでミドルウェアを作成します。
php artisan make:middleware ShareUserVariables
次に、作成されたミドルウェアを編集します。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Auth;
class ShareUserVariables
{
public function handle(Request $request, Closure $next): Response
{
// ミドルウェア内であれば、セッションや認証情報にアクセスできます
if (Auth::check()) {
View::share('currentUserRole', Auth::user()->role);
}
return $next($request);
}
}
Laravel 11では、ミドルウェアの登録は bootstrap\app.phpで行います。Webルート全体に適用する場合は以下のように追記します。
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
// webミドルウェアグループに追加して、すべてのWebリクエストで実行させます
$middleware->web(append: [
\App\Http\Middleware\ShareUserVariables::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
4. まとめ
各手法を比較すると以下の表のようになります。
| 方法 | 実行タイミング | 適しているデータ | メリット |
|---|---|---|---|
| share() | アプリ起動時(全てのビュー) | 静的な設定値、アプリ全体の共通定数 | 最も手軽に書ける |
| composer() | 指定ビューの描画直前 | DBから取得する重いデータ、特定パーツ専用のデータ | 無駄な処理が走らずパフォーマンスが良い |
| ミドルウェア | HTTPリクエスト受信後 | ログインユーザー情報、セッションの状態 | ユーザーの状態(セッション等)を利用できる |
5. おわりに
サービスプロバイダー・ミドルウェアの仕組みは複雑でしたが、この記事を参考に実装していただければと思います。