概要
初めて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
出来たマイグレーションファイルにテーブルを追加します。
~~省略~~
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モデルに適当なデータを入れます。
<?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.コントローラーを設定する
<?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.ルーティングを設定する
<?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を編集します。真ん中と下の方にコードを追加します。
// 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の公式ページからワイヤーフレームを選択します。
※公式ページは英語版と日本語版がありますが、日本語版だとうまくいかなかったので英語版の方をつかってください。
右下の青色のgithubのマークをクリックします。
その後、出てきたコードをコピーし、先ほど作ったresources/js/Pages/Tests/Index.vue
に貼り付けます。
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>
全体像
<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にコントローラーから変数を渡せています。
まとめ
調べても同じ環境の記事が見つからず結構苦戦しました。
特にapp.js
ファイルの設定は調べてもなかなかうまくいかず、vuetifyのデザインが消失したり、エラーが出たりと大変でしたが、何とかうまくいってよかったです。