0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Laravel Inertia】ほな Laravel から Vue へはどうやって値を渡すのよ

Last updated at Posted at 2025-12-04

これじゃ型のアドベントカレンダーじゃないか!
ということで実践編です。

正直型問題をクリアしないと vilt スタック微妙なんですよ。
OpenAPI 使ってフロントバック分けたほうが見通しが良い。。。

逆に型問題をクリアした VILT スタックは強すぎます。現環境最強?です。

以下 React でもできるんですが、私が Vue 信者なので Vue ですすめますね。

ページの表示

基本的には Laravel の Blade と似た感じで運用することができます。
試しに GET /test というルートに、ユーザーデータを渡す処理を作ってみます。

TestController.php は __invoke() で作っても良き。

routes/web.php
use App\Http\Controllers\TestController;
use Illuminate\Support\Facades\Route;

Route::get('/test', [TestController::class, 'index']);

コントローラーでは、通常の処理と同じように書きますが、 return にて Inertia::render() を返却します。
これは Blade の view() と同じ仕組みで、第一引数に View 、第二引数に渡す変数を指定することができます。
ビューは resources/js/pages/XXX/YYY.vue であれば XXX/YYY と記載すればOKです。
変数は自動的に JSON 化して渡されます。

変数は compact() を使うのも良き。

app/Http/Controllers/TestController.php
namespace App\Http\Controllers;

use App\Models\User;
use Inertia\Inertia;

class TestController extends Controller
{
    public function index()
    {
        $users = User::limit(5)->get();

        return Inertia::render('Test', [
            'users' => $users,
        ]);
    }
}

その値をどうやって受け取るのかというと、コンポーネントのように defineProps() でそのまま受け取ることができます。

ここで前述の記事で自動生成したモデルの型を使うことで、何の苦労もなくフロントとバックを繋ぐことができます。
これが VILT スタックAPI です。

resources/js/pages/Test.vue
<template>
  <table class="m-4 border-collapse border-2">
    <thead>
      <tr>
        <th class="p-2 border-2">ID</th>
        <th class="p-2 border-2">Name</th>
        <th class="p-2 border-2">Email</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="user of users" :key="user.id">
        <td class="p-2 border-2">{{ user.id }}</td>
        <td class="p-2 border-2">{{ user.name }}</td>
        <td class="p-2 border-2">{{ user.email }}</td>
      </tr>
    </tbody>
  </table>
</template>

<script setup lang="ts">
defineProps<{
  users: App.Models.User[],
}>()
</script>

ででん!

image.png

こんな感じで繋げるため Vue 側には Router がありません。

Layout の付け方

じゃぁ Layout ってどうやって使うの?ってなると思います。
それは defineOptions() で定義することができます。

layouts ディレクトリを js 配下に作って、レイアウトファイルを作成します。

resources/js/layouts/BaseLayout.vue
<template>
  <div class="m-2 bg-blue-950">
    <slot></slot>
  </div>
</template>

それをページルートの defineOptions() に読ませばOKです。

// ...

<script setup lang="ts">
import BaseLayout from '@/layouts/BaseLayout.vue'

defineOptions({
  layout: BaseLayout
})

// ...

defineOptions() は最近できたマクロなんですが、 inheritAttrs とかもかける便利な奴です。
わざわざ <script> を書かなくて済むので神です。

データ共有(疑似セッション)

もう一つ共有の方法があります。

いわゆる session() ですね。
ただ Inertia を利用していると Laravel の Session はそのまま使えません...。

疑似 SPA の構成なので、セッションの再読み込みがかかったり、かからなかったり...
この手法を知るまで謎のバグに会い続けていた...。

デフォルトでは HandleInertiaRequests というミドルウェアが用意されていて、こちらを使うことでフロントと値を共有することができます。

app/Http/Middleware/HandleInertiaRequests.php
public function share(Request $request): array
{
    [$message, $author] = str(Inspiring::quotes()->random())->explode('-');

    return [
        ...parent::share($request),
        'name' => config('app.name'),
        'quote' => ['message' => trim($message), 'author' => trim($author)],
        'auth' => [
            'user' => $request->user(),
        ],
    ];
}

デフォルトだとこんな感じのものが書かれていると思います。
簡単に言うと、こちらに指定したものが json となって毎通信フロントに渡ります。

quote はサンプル用に用意された、偉人の言葉が返ってくる変数になってます。

ここで定義したオブジェクトは、フロント側にあらかじめ定義されている AppPageProps と型を合わせてください。
ちなみに UserApp.Models.User に置き換えると、自動型生成のサイクルに組み込むことができて幸せになります。

resources/js/types/index.d.ts
export interface Auth {
    user: User;
}

export type AppPageProps<T extends Record<string, unknown> = Record<string, unknown>> = T & {
    name: string;
    quote: { message: string; author: string };
    auth: Auth;
};

Inerita のフロントには usePage() という composable が存在します。
この中の props に上記値が入っています。

ためしに quote を取り出してみると、

resources/js/pages/Test.vue
<template>
  <pre class="m-4">{{ page.props.quote }}</pre>
</template>

<script setup lang="ts">
import { usePage } from '@inertiajs/vue3'

const page = usePage()

// ...
</script>

こんな感じで取り出すことができます。

image.png

ちゃんと TypeHint も出るので、とても楽ですね。

image.png

Share はページと関係なく常に同期したい、Laravel の設定情報や、認証ユーザーの情報、トーストの通知情報など、で利用すると良いです。
ただ毎通信のペイロードに乗るため、乗せすぎは注意です。

遅延取得

Inertia 全般に言えるのですが、値をフロントに渡す際に fn () でくるんで関数を渡すことができます。
fn () でくるんでおくと、必要な時に関数を実行して値を取り出して、取り出してくれる computed のような挙動をします。

何か挙動がおかしいと思ったときは、この fn () が足りていないことが多いので、つけてみましょう。

[
    'normal' => User::get(),
    'wrap' => fn () => User::get(),
]

詳しくは割愛しますが、Inertia は部分取得することが多いので、覚えておきましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?