Laravel

【サンプルあり】Laravel Auth のログイン画面を Vuetify仕様に置き換えよう!

みなさん、こんにちは。どんぶラッコです。

前回、LaravelでVuetifyを使えるようにするまでの手順を解説しました。

VueでLaravel標準の認証機能を使うには、

composer require laravel/ui
php artisan ui vue --auth

のコマンドを実行すればOKでした。

しかし、このままでは、ログインページ画面はbootstrapで作成された標準画面のままです。

今回はこの部分をVuetify仕様に置換えてみましょう!

どんぶラッコ
どんぶラッコ
完成イメージはこんな感じだよ!

変更手順

では、実際にどのように変更していくのかというと…

変更手順
  1. Vuetifyをインストール
  2. layout.v-app を作成
  3. login.blade.phpを編集

です。

  1. Vuetifyをインストール

の手順については冒頭にご紹介した記事を参考に進めてください。

ということで早速手順2から進めていきましょう!

2. layout.v-app を作成

resources/view/layouts/ ディレクトリ内に v-app.blade.phpを作成します。

名無しさん
名無しさん
layoutsには何が格納されているの?
どんぶラッコ
どんぶラッコ
ヘッダやフッタなど、共通レイアウトの記述がされているファイルが格納されている場所だよ。
既にある `app.blade.php` を書き換えてもいいんだけど、今回は新規でレイアウトファイルを作成してみましょう!

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Sample') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
    <v-app style="background-color: #F1F6FB;">
        <v-app-bar color="white" height="80" app clipped-left>
            <v-toolbar-title>
                <img src="{{ asset('assets/logo.png') }}" alt="logo" class="logo-img">
            </v-toolbar-title>
            <v-spacer></v-spacer>
            @guest
                <v-btn text href="{{ route('login') }}">{{ __('Login') }}</v-btn>
                @if (Route::has('register'))
                    <v-btn text href="{{ route('register') }}">{{ __('Register') }}</v-btn>
                @endif
            @else
                <v-menu offset-y>
                    <template v-slot:activator="{ on, attrs }">
                        <v-btn
                            text
                            v-bind="attrs"
                            v-on="on"
                        >
                            {{ Auth::user()->name }}
                        </v-btn>
                    </template>
                    <v-list>
                        <v-list-item href="{{ route('logout') }}"
                                     onclick="event.preventDefault();
                                                     document.getElementById('logout-form').submit();">
                            <v-list-item-title>
                                    {{ __('Logout') }}
                            </v-list-item-title>
                        </v-list-item>
                    </v-list>
                    <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
                        @csrf
                    </form>
                </v-menu>
            @endguest
        </v-app-bar>
        <v-main>
            @yield('content')
        </v-main>
    </v-app>
</div>
</body>
</html>

<header></header> 部分については、デフォルトで実装されている app.blade.php からほぼコピーしてきたものなので説明は割愛します。

<body></body> 内の構造も至ってシンプルですね。 <div id="app"> で全体を括ることで、vueで管理する対象を指定しています。

<body>
<div id="app">
...
</div>
</body>

また、レイアウトについては v-appの機能を使っています。

    <v-app style="background-color: #F1F6FB;">
        <v-app-bar color="white" height="80" app clipped-left>
           ...
        </v-app-bar>
        <v-main>
            @yield('content')
        </v-main>
    </v-app>
どんぶラッコ
どんぶラッコ
わかりやすくするためv-appの背景を直接 styleで指定してしまっていますが、良い子のみんなはClassに切り分けてね!

3. login.blade.phpを編集

さて、下準備が整ったら、login.blade.phpを編集していきましょう!

以下のサンプルのように書き換えてみてください

@extends('layouts.v-app')

@section('content')
<v-main>
    <v-container>
        <h1 class="h4 text-center pt-8 font-weight-bold">
            {{ __('Login') }}
        </h1>
        <v-row justify="center">
            <v-col cols="12" md="6">
                <v-card elevation="0">
                    <div class="pa-8">
                        <form method="POST" action="{{ route('login') }}">
                            @csrf
                            <p class="mb-0 font-weight-bold">{{ __('E-Mail Address') }}</p>
                            <v-text-field
                                outlined
                                type="email"
                                name="email"
                                value="{{ old('email') }}"
                                v-bind:error="@error('email') true @else false @enderror"
                                error-messages="@error('email') {{$message}} @enderror"
                                required
                                autocomplete="email"
                                placeholder="example@example.com"
                                autofocus
                            ></v-text-field>

                            <p class="mb-0 font-weight-bold">{{ __('Password') }}</p>
                            <v-text-field
                                outlined
                                type="password"
                                name="password"
                                v-bind:error="@error('password') true @else false @enderror"
                                error-messages="@error('password') {{$message}} @enderror"
                                required
                                autocomplete="current-password"
                            ></v-text-field>

                            <v-checkbox
                                name="remember"
                                label="{{ __('Remember Me') }}"
                                value="{{ old('remember') ? 'true' : 'false' }}"
                                class="mb-12"
                            ></v-checkbox>

                            <div class="px-4 mb-4">
                                <v-btn type="submit" color="primary" elevation="0" block large>
                                    {{ __('Login') }}
                                </v-btn>
                            </div>

                            @if (Route::has('password.request'))
                                <div class="text-center">
                                    <a class="btn btn-link" href="{{ route('password.request') }}">
                                        {{ __('Forgot Your Password?') }}
                                    </a>
                                </div>
                            @endif
                        </form>
                    </div>
                </v-card>
            </v-col>
        </v-row>
    </v-container>
</v-main>
@endsection

こちらもlaravel標準の画面では <input> タグで表現されていた部分をv-text-fieldv-checkboxで置換えていっているだけなので、直感的にわかりやすいかな、と思います。

ポイントは一番最初の行の

@extends('layouts.v-app')

です。 layouts.v-app を指定することで、先ほど作成した resources/view/layouts/v-app.blade.phpを呼び出しています。

そして、

@section('content')
...
@endsection

で囲われた部分が、 v-app.layout.php 内の

@yield('content')

に埋め込まれた状態で出力が返されます。

名無しさん
名無しさん
この “@…” は Laravelの機能だね!
どんぶラッコ
どんぶラッコ
LaravelとVueを併用すると両者の固有の書き方で混乱すると思います。
一つずつ落ち着いて整理していきましょう!

以上で書き換えを完了することができました!

v-app.blade.phpは他のページでも使うことができます。

どんどん展開させていってしまいましょう♪

ABOUT ME
どんぶラッコ
ECコンサルタント、システムエンジニアを経て、quintet株式会社CTOに就任。普段はNuxt.jsやLaravelを使用しています。

\面白いと思ったら/

記事のシェア & Twitter のフォロー をお願いします!

@proglearn
RELATED POST

COMMENT

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です