laravel8.x:変わりすぎて戸惑った仕様についての備忘録

laravel8.x:変わりすぎて戸惑った仕様についての備忘録

悩む案件抱えると途端に更新できなくなるこのブログ。
という事で、2週間ぶりの新規記事です。

現在動いている案件にて【Laravel8系】で構築することになったのですが、こいつが6系と変わりすぎていて解読に時間を要してしまいました。今回は8系に変えた際の『悩みポイント』についてザクっとまとめます。

8系で変更はSPAを意識した変更が多く、私の悩みポイントは下の項目でした。

  1. Auth仕様の変更
  2. npm run dev でエラーが発生し動かない
  3. router\web.php でのコントローラー呼び出し方法がわからない
  4. app\View\Components の存在と利用
  5. bootstrapからTailwindへの標準CSS変更

Auth仕様の変更

ログイン関連もこの影響を大きく受け、JetStreamという企画を標準仕様になりました。
7系で実装されていたnode.jsを使った仕組みの完成形になるようです。

AuthControllerを作成して地道に構築していくこともできますが、単純構成であればLaravel/ui を使う方が簡単です。
Laravel 8.x 認証(公式) / 参考サイト

  1. JetStream をインストール [ composer require laravel/jetstream ]
    ※ プロジェクト作成と同時にインストールする時  => [ laravel new プロジェクト名 --jet ]
  2. JetStream をセットアップ
    ・SPAで構築 [ php artisan jetstream:install inertia ]
    ・bladeで書く [ php artisan jetstream:install livewire ]
    ・チーム機能利用 [ php artisan jetstream:install livewire --teams ]
  3. マイグレーション実行 [ php artisan migrate ]
    ※コマンドを実行すると、database\migrations に下のファイルが作られます。
    ・create_users_table.php
    ・create_password_resets_table.php
    ・add_two_factor_columns_to_users_table.php
    ・create_failed_jobs_table.php
    ・create_personal_access_tokens_table
    ・create_teams_table (※ --teams で設定したとき)
    ・create_team_user_table (※ --teams で設定したとき)
    ・create_sessions_table
  4. npmのインストールと起動 [ npm install && npm run dev ]
    ※エラーが発生する場合は後述する方法でモジュールを最新にします。

npm run dev でエラーが発生し動かない

順調にインストールをしたと思っていたところ【 npm run dev 】を実行するとエラーが発生しLaravel側からもErrorのアナウンスが出ました。
npm run dev でエラーが発生すると laravel-mix が起動せずLaravel全体が動作不良になります。

このエラーですが、Docker構築時にnode.js / module / npm の関係性で不整合が見つかると起こるようです。
という事で、解決策は『最新の状態に更新する事』
右往左往しましたが、私も最終的にこの方法で解決できました。

# Laravelの格納されたコンテナに入ってLaravelプロジェクトディレクトリで下記コマンドを順に実行

  $ npm install n -g
  $ n stable
  $ apt purge -y nodejs npm
  $ npm rebuild
  $ exec $SHELL -l
  $ npm run dev

上のコマンドは具体的に何を行っているか

node.js と npm を最新の状態にし、古いパッケージを削除、最後にnpmを起動しています。
これでエラーは解消されるはず。

router\web.php でのコントローラー呼び出し方法がわからない

順調にログイン周りが出来「さぁ色々作るか」となっても大きな課題が...。

× => Route::resource('users', 'UserController');
〇 => Route::resource('users', 'App\Http\Controllers\UserController');

今までだと自動で処理していてくれた Controllers への導線ですが、8.x では用意されていません。
なので、use してショートコマンドで動かすか、パスをそのまま支持するかの2択となります。

<?php
use App\Http\Controllers\WelcomeController;

Route::get('/',  [WelcomeController::class, 'welcome']);
  # 上と同じ意味
  # Route::get('/',  'App\Http\Controllers\WelcomeControllerWelcomeController', 'welcome']);
  # useしていれば下もOK
  # Route::get('/', 'WelcomeControllerWelcomeController', 'welcome']);

# authを通った人にだけ見せたい時
Route::name('list')->middleware(['auth:'.'users', 'verified'])
        ->resource('/list', ListController::class);

app\View\Components の存在と利用

viewsにディレクトリを置いて単純にindex.phpなどを記載していたら意図した表示にならず調べたらコレが問題でした。Laravel8の提供するテンプレートには標準仕様として app\View\Components に配置したrenderを見るように仕掛けられています。
▼ resources\views\auth\login.blade.php ※ <x-guest-layout> : app\View\Components\GuestLayout.phpに展開

<x-guest-layout>
    <x-jet-authentication-card>
        <x-slot name="logo">
            <x-jet-authentication-card-logo />
        </x-slot>

        <x-jet-validation-errors class="mb-4" />

        @if (session('status'))
            <div class="mb-4 font-medium text-sm text-green-600">
                {{ session('status') }}
            </div>
        @endif

        <form method="POST" action="{{ route('login') }}">
            @csrf

            <div>
                <x-jet-label for="email" value="{{ __('Email') }}" />
                <x-jet-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
            </div>

            <div class="mt-4">
                <x-jet-label for="password" value="{{ __('Password') }}" />
                <x-jet-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="current-password" />
            </div>

            <div class="block mt-4">
                <label for="remember_me" class="flex items-center">
                    <x-jet-checkbox id="remember_me" name="remember" />
                    <span class="ml-2 text-sm text-gray-600">{{ __('Remember me') }}!!!</span>
                </label>
            </div>

            <div class="flex items-center justify-end mt-4">
                @if (Route::has('password.request'))
                    <a class="underline text-sm text-gray-600 hover:text-gray-900" href="{{ route('password.request') }}">
                        {{ __('Forgot your password?') }}
                    </a>
                @endif

                <x-jet-button class="ml-4">
                    {{ __('Log in') }}
                </x-jet-button>
            </div>
        </form>
    </x-jet-authentication-card>
</x-guest-layout>

▼ app\View\Components\GuestLayout.php ※return view('layouts.guest'); resources\views\layouts\guest.blade.php を展開

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class GuestLayout extends Component
{
    /**
     * Get the view / contents that represents the component.
     *
     * @return \Illuminate\View\View
     */
    public function render()
    {
        return view('layouts.guest');
    }
}

▼ resources\views\layouts\guest.blade.php ※{{ $slot }}:resources\views\auth\login.blade.phpの<x-slot>を展開

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

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

        <!-- Fonts -->
        <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap">

        <!-- Styles -->
        <link rel="stylesheet" href="{{ mix('css/app.css') }}">

        <!-- Scripts -->
        <script src="{{ mix('js/app.js') }}" defer></script>
    </head>
    <body>
        <div class="font-sans text-gray-900 antialiased">
            {{ $slot }}
        </div>
    </body>
</html>

アッチ行ったりコッチ行ったりという感じではありますが、app\View\Components\ で指示したファイルが基盤のテンプレートとして展開されています。

bootstrapからTailwindへの標準CSS変更

今回一番悩んだかもしれないTailwind。
Laravelerな私は bootstrap に慣れていたのでもう書き方が良く分からない。
で、Bootstrapにしてしまおうとインストール&読込を実行したら画面総崩れ。
当たり前ですよね、標準CSSが違うのですから。
で、崩れたから元に戻そうとしたところ戻らない。

原因はnode.js がCSSを管理していて {{ mix('css/app.css') }} で出力しているため。
node側の設定からBootstrapを除外しなくてはならないという理屈でした。
下の様に Tailwind を有効にし、Bootstrapを除外すれば元に戻ります。

▼ resources\sass\app.scss

// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');

// Tailwind CSS
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

// Variables
//@import 'variables';
// Bootstrap
//@import '~bootstrap/scss/bootstrap';

// Font Awesome
@import '~@fortawesome/fontawesome-free/scss/fontawesome';
@import '~@fortawesome/fontawesome-free/scss/regular';
@import '~@fortawesome/fontawesome-free/scss/solid';
@import '~@fortawesome/fontawesome-free/scss/brands';

まとめ

Laravel8.xでこんなに変更点があるとは思いませんでした。
GWがあったおかげで分析に時間かけることできましたが、納期詰まった案件だったらきつかったと思います。

2段階認証が付いているなどの機能を使いたくてLaravel8を選択したのですが、安易にフレームワーク選択しちゃだめですね。
いい勉強になりました。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください