LoginSignup
5
3

More than 1 year has passed since last update.

【未経験】Laravel10 + Sail + Inertia + Vue3アプリでVuetify3のワイヤーフレームを使いコントローラーから変数を渡すまで

Last updated at Posted at 2023-06-17

概要

初めてVuetifyを使いましたがLaravel10 + Sail + Inertia + Vue3を使ったアプリでVuetify3を使う記事が見当たらず苦戦したので備忘録として残します。

まだ初心者のため間違いがあるかもしれませんがコメントで教えていただけると助かります。

※Laravelについての知識があるのは前提とします。

環境

WSL2
Ubuntu 22.04.2 LTS

手順

1.Laravel10 + Sail + Inertia + Vue3のセットアップ

私はこちらの動画を参考にしました。とても分かりやすかったのでこちらの動画を見るのが早いと思いますが一応下に手順を記します。動画を参考にする方は4.モデルやコントローラーを作成するまで飛ばしてください。

こちらの動画ではvueは使っていないので11:13./vendor/bin/sail artisan breeze:installの際にvueを選択してください。

2.Laravel10をSail(Dokcer)で立ち上げる

コマンドラインで以下のコマンドを入力する。example-appの部分は自分のプロジェクト名にしてください。
途中でパスワードの入力を求められますので入力します。

curl -s "https://laravel.build/example-app" | bash

#参考
https://readouble.com/laravel/10.x/ja/installation.html

3.breezeのインストール

まずはsailを起動します。

./vendor/bin/sail up

その後以下のコマンドを入力

./vendor/bin/sail composer require laravel/breeze --dev
./vendor/bin/sail artisan breeze:install

この時viewに何を使用するか選べるのでここでvueを選択。
その後は自由に選べますがこだわりがなければ全てEnterを入力。

 Which stack would you like to install?
  blade ...................................................................... 0  
  react ...................................................................... 1  
  vue ........................................................................ 2  
  api ........................................................................ 3  
❯ 2

  Would you like to install dark mode support? (yes/no) [no]
❯ 

  Would you like TypeScript support? (Experimental): (yes/no) [no]
❯ 

  Would you like to install Inertia SSR support? (yes/no) [no]
❯ 

  Would you prefer Pest tests instead of PHPUnit? (yes/no) [no]
❯ 

その後migrateします。

./vendor/bin/sail artisan migrate

4.モデルやコントローラーを作成する

モデルやコントローラーを作成します。名前はご自身のプロジェクトによってきめてください。
今回はTestという名前で作ります。

./vendor/bin/sail php artisan make:model Test -a 

出来たマイグレーションファイルにテーブルを追加します。

database/migrations/2023_06_17_133705_create_tests_table.php
~~省略~~
    public function up(): void
    {
        Schema::create('tests', function (Blueprint $table) {
            $table->id();
            $table->string('text'); //追加
            $table->timestamps();
        });
    }

~~省略~~

その後migrateします。

./vendor/bin/sail artisan migrate

5.DBに適当なデータを入れる

出来たTestモデルに適当なデータを入れます。

database/seeders/TestSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB; //追加
use Illuminate\Support\Str; //追加

class TestSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        //textにランダムな文字列を追加したものを10件ほど作成する
        for ($i = 0; $i < 10; $i++) {
            DB::table('tests')->insert([
                'text' => Str::random(10),
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        }
    }
}

以下のコマンドで生成する

./vendor/bin/sail php artisan db:seed --class=TestSeeder

6.コントローラーを設定する

app/Http/Controllers/TestController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreTestRequest;
use App\Http\Requests\UpdateTestRequest;
use App\Models\Test; //追加
use Inertia\Inertia;

class TestController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        // 先ほど作ったデータを$testsに入れる
        $tests = Test::all();
        
        // Tests/Indexに$testsを渡す
        return Inertia::render('Tests/Index', [
            'tests' => $tests,
        ]);
    }

~~省略~~

7.ルーティングを設定する

routes/web.php
<?php

use App\Http\Controllers\ProfileController;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
use App\Http\Controllers\TestController; //追加

Route::resource('test', TestController::class); //追加

~~省略~~

8.Vuetify3のインストール

Yarnを使いVuetify3をインストールします。

yarn add vuetify@^3.3.4

VuetifyのMaterial Design Iconsもインストールします。

yarn add @mdi/font

9.Vuetifyのセットアップ

app.jsを編集します。真ん中と下の方にコードを追加します。

resources/js/app.js
// import "./bootstrap";
// import "../css/app.css";

import { createApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/inertia-vue3";
import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers";
import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m";

// ここから
import "vuetify/dist/vuetify.min.css";
import App from "./Pages/Tests/Index.vue";
import "@mdi/font/css/materialdesignicons.css"; 
import "vuetify/styles";
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";

const vuetify = createVuetify({
    components,
    directives,
});
// ここまで追加

const appName =
    window.document.getElementsByTagName("title")[0]?.innerText || "Laravel";

createInertiaApp({
    title: (title) => `${title} - ${appName}`,
    resolve: (name) =>
        resolvePageComponent(
            `./Pages/${name}.vue`,
            import.meta.glob("./Pages/**/*.vue")
        ),
    setup({ el, App, props, plugin }) {
        return createApp({ render: () => h(App, props) })
            .use(vuetify) //追加
            .use(plugin)
            .use(ZiggyVue, Ziggy)
            .mount(el);
    },
    progress: {
        color: "#4B5563",
    },
});

10.Viewを作成する

resources/js/Pagesの中にTestsフォルダを作り、その中にIndex.vueファイルを作成します。

11.Vuetifyのワイヤーフレームを使う

Vuetifyの公式ページからワイヤーフレームを選択します。
※公式ページは英語版と日本語版がありますが、日本語版だとうまくいかなかったので英語版の方をつかってください。

今回はこちらを選択します。
スクリーンショット (69).png

右下の青色のgithubのマークをクリックします。
その後、出てきたコードをコピーし、先ほど作ったresources/js/Pages/Tests/Index.vueに貼り付けます。

スクリーンショット (71).png

12.アプリケーションを立ち上げる

以下の2つのコマンドでアプリケーションを立ち上げます。

vendor/bin/sail up
npm run dev

ここでlocalhost/testsにアクセスすると先ほど選択したワイヤーフレームが表示されていると思います。

13.コントローラーから変数を渡す

「6.コントローラーを設定する」ですでに$testsをview側に渡しているのでIndex.vueを以下のように編集します。

<script setup>
import { ref } from "vue";

// コントローラーから渡された値を受け取る
defineProps({
    tests: {
        type: String,
        required: true,
    },
});
<!-- testsを繰り返し表示する -->
<template v-for="test in tests" :key="test.id">
    <v-list-item>
        <template v-slot:prepend>
            <v-avatar color="grey-darken-1"></v-avatar>
        </template>

        <v-list-item-title>
            {{ test.text }}
        </v-list-item-title>
    </v-list-item>
    <!-- v-list-item-subtitleは今回は邪魔なので削除する -->
    <!-- <v-list-item-subtitle>
        Lorem ipsum dolor sit amet,
        consectetur adipisicing elit. Nihil
        repellendus distinctio similique
    </v-list-item-subtitle> -->
    <v-divider
        v-if="test.id !== 6"
        :key="`divider-${test.id}`"
        inset
    ></v-divider>
</template>

全体像

resources/js/Pages/Tests/Index.vue
<template>
    <v-app id="inspire">
        <v-system-bar>
            <v-spacer></v-spacer>

            <v-icon>mdi-square</v-icon>

            <v-icon>mdi-circle</v-icon>

            <v-icon>mdi-triangle</v-icon>
        </v-system-bar>

        <v-navigation-drawer v-model="drawer">
            <v-sheet color="grey-lighten-4" class="pa-4">
                <v-avatar
                    class="mb-4"
                    color="grey-darken-1"
                    size="64"
                ></v-avatar>

                <div>john@google.com</div>
            </v-sheet>

            <v-divider></v-divider>

            <v-list>
                <v-list-item v-for="[icon, text] in links" :key="icon" link>
                    <template v-slot:prepend>
                        <v-icon>{{ icon }}</v-icon>
                    </template>

                    <v-list-item-title>{{ text }}</v-list-item-title>
                </v-list-item>
            </v-list>
        </v-navigation-drawer>

        <v-main>
            <v-container class="py-8 px-6" fluid>
                <v-row>
                    <v-col v-for="card in cards" :key="card" cols="12">
                        <v-card>
                            <v-list lines="two">
                                <v-list-subheader>{{ card }}</v-list-subheader>

                                <template v-for="test in tests" :key="test.id">
                                    <v-list-item>
                                        <template v-slot:prepend>
                                            <v-avatar
                                                color="grey-darken-1"
                                            ></v-avatar>
                                        </template>

                                        <v-list-item-title>
                                            {{ test.text }}
                                        </v-list-item-title>
                                    </v-list-item>

                                    <v-divider
                                        v-if="test.id !== 6"
                                        :key="`divider-${test.id}`"
                                        inset
                                    ></v-divider>
                                </template>
                            </v-list>
                        </v-card>
                    </v-col>
                </v-row>
            </v-container>
        </v-main>
    </v-app>
</template>

<script setup>
import { ref } from "vue";

// コントローラーから渡された値を受け取る
defineProps({
    tests: {
        type: String,
        required: true,
    },
});

const cards = ["Today", "Yesterday"];
const links = [
    ["mdi-inbox-arrow-down", "Inbox"],
    ["mdi-send", "Send"],
    ["mdi-delete", "Trash"],
    ["mdi-alert-octagon", "Spam"],
];

const drawer = ref(null);
</script>

以下のようにランダムな文字列が表示されていたらVuetify3を使ったviewにコントローラーから変数を渡せています。

スクリーンショット (73).png

まとめ

調べても同じ環境の記事が見つからず結構苦戦しました。
特にapp.jsファイルの設定は調べてもなかなかうまくいかず、vuetifyのデザインが消失したり、エラーが出たりと大変でしたが、何とかうまくいってよかったです。

5
3
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
5
3