ホーム » 【Laravel】プログラミング初心者向けの実践入門!スキルアプリを作ってみよう!

【Laravel】プログラミング初心者向けの実践入門!スキルアプリを作ってみよう!

Table of Contents

composerをインストールする

1.下記リンクを元に、comopserをinstallする。

https://getcomposer.org/download/
googleで「composer download」で検索してください。

↓下記はサイトに書いてある情報のコピーです。まずは上記のリンクを確認ください。

				
					
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
				
			

・composer.pharファイルのパスを通す。

下記コマンドを実行することによって、composer installのように実行できるようになります。

				
					
$ sudo mv composer.phar /usr/local/bin/composer
				
			

※ $は入力しなくていいです。$は、ターミナルに表示されている$を一般的に表現します。

Laravel SailでLaravelをインストールする

1.laravelをインストールする。

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

※example-appがアプリの名前です。

Laravel Sailでdocker upをします

1.sail upでdockerを立ち上げる

				
					
cd skills
./vendor/bin/sail up
				
			

2.sailのエイリアス設定
そのプロジェクトでsailコマンドが楽になる。

				
					
$ alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'

alias sail="vendor/bin/sail"
source .zshrc
				
			

最初のプログラムを作ってみよう【ルーティング】

1.laravelのディレクトリに移動する

				
					
$ cd /Users/imanaka/works/skills # <-こちらのディレクトリはサンプルです。
				
			

2.artisanコマンドでコントローラーを作成する

				
					
$ sail php artisan make:controller ExampleController
				
			

※sailコマンドは、パスを通していない場合は、下記で実行ください。

				
					
$ ./vendor/bin/sail
				
			

3.bladeを作成する
welcome.blade.phpをコピーしてexample.blade.phpを作成する。

※ $はターミナルのプロンプトを表現してますので、実行しなくて大丈夫です。

				
					
<?php

use App\Http\Controllers\ExampleController;
use Illuminate\Support\Facades\Route;

return Route::get('/example', [ExampleController::class, 'index']);
				
			

最初のプログラムを作ってみよう【コントローラー】

ExampleController.phpを下記内容にします。

				
					
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ExampleController extends Controller
{
    //
    public function index()
    {
        return view('welcome');
    }
}
				
			

最初のプログラムを作ってみよう【ビュー】

example.blade.phpを下記内容にします。

				
					
<!DOCTYPE html>
<html>
<body>
<h1><span class="ez-toc-section" id="example%E3%83%96%E3%83%AC%E3%83%BC%E3%83%89%E3%81%A7%E3%81%99%E3%80%82"></span>exampleブレードです。<span class="ez-toc-section-end"></span></h1>
</body>
</html>
				
			

最初のプログラムを作ってみよう【モデル】

1.Exampleモデルを作成する

				
					
$ sail php artisan make:model Example
				
			

skills/app/Models/Example.phpファイルが作成されます。

				
					
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Example extends Model
{
    use HasFactory;
}

				
			

最初のプログラムを作ってみよう【マイグレーション作成】

1.マイグレーションファイルの作成をする

				
					
$ sail php artisan make:migration create_examples_table

				
			

skills/database/migrations/2021_08_20_110205_create_examples_tableのようなファイルが作成されます。
※2021_08_20_110205は日付です。実行時の日付が入ります。

				
					
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateExamplesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('examples', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('examples');
    }
}

				
			

最初のプログラムを作ってみよう【マイグレーション実行】

1.マイグレーションファイルを実行する

				
					
$ sail php artisan migrate
				
			

データベース管理ツール【Workbench】のインストール

1.MySQL Workbenchのダウンロード

https://www.mysql.com/jp/products/workbench/

データベース管理ツール【Workbench】の設定

MySQL Workbenchの設定

1.[.env]ファイルの内容をWorkbenchに設定する

※:より左が項目名、右が入力名です。

				
					
Connection Name:skills
Default Schema:skills
Username:sail
Password:password
				
			

データベースシーダー作成

1.データベースシーダーを作成する

				
					
$ sail php artisan make:seeder ExampleSeeder
				
			

データベースシーダー実行

1.データベースシーダーを実行する

				
					
$ sail php artisan db:seed --class=ExampleSeeder
				
			
				
					
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class ExampleSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('examples')->insert([
            'id' => 10,
        ]);
    }
}

				
			

データベースシーダーで挿入されたファイルを確認する

1.データベースに格納されているテーブルの中身を検索する

				
					
select * from examples;
				
			

コントローラーでモデルを利用する

1.ExampleController.phpにModelを記述します。

				
					
$examples = Example::all();
				
			

2.ExampleController.phpにview(example.blade.php)に変数($examples)を渡します。

				
					
return view('example', [
    'examples' => $examples
]);
				
			

3.example.blade.phpで変数($examples)を受け取ります。

				
					
{{ $examples }}
				
			
				
					
<?php

namespace App\Http\Controllers;

use App\Models\Example;
use Illuminate\Http\Request;

class ExampleController extends Controller
{
    //
    public function index()
    {
        $examples = Example::all();
        return view('example', [
            'examples' => $examples
        ]);
    }
}

				
			
				
					
<!DOCTYPE html>
<html>
<body>
<h1><span class="ez-toc-section" id="example%E3%83%96%E3%83%AC%E3%83%BC%E3%83%89%E3%81%A7%E3%81%99%E3%80%82-2"></span>exampleブレードです。<span class="ez-toc-section-end"></span></h1>
{{ $examples }}
</body>
</html>
				
			

Laravel Breezeでログイン機能を実装する

				
					
$ sail composer require laravel/breeze --dev
$ sail php artisan breeze:install # breezeをインストールすると、tailwindcssの設定がされる。
$ sail npm install

$ sail root-shell
$ npm install -g npm@7.22.0

$ sail npm run dev
$ sail php artisan migrate
				
			

■sail npm installが失敗する場合
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: “npm”: executable file not found in $PATH: unknown
→ dockerのアップデート+docker buildで解決することがあります。

Laravel Breezeでログイン機能を日本語化する

1.日本語化(バリデーションなどの翻訳データ)データを下記からダウンロード
https://github.com/Laravel-Lang/lang

2.resources/lang/jsに配置してja.jsonは、lang配下におく
resources/lang/ja.json

日本語化(バリデーションなどの翻訳データ)
https://github.com/Laravel-Lang/lang

・Document
https://readouble.com/laravel/8.x/ja/localization.html

スキルテーブルを作成する

1.Skillsモデルの作成

				
					
$ sail php artisan make:model Skill
				
			

2.マイグレーションファイルの作成をする

				
					
$ sail php artisan make:migration create_skills_table
				
			

3.マイグレーションファイルを修正する

2021_08_23_233710_create_skills_table.php # こちらは「日付_create_skills_table.php」のファイルが作成されます。

				
					
Schema::create('skills', function (Blueprint $table) {
    $table->id();
    $table->string('skill_name');
    $table->integer('skill_status');
    $table->timestamps();
});
				
			

4.マイグレーションファイルを実行する

				
					
$ sail php artisan migrate
				
			

5.データベースシーダーを作成する

				
					
$ sail php artisan make:seeder SkillSeeder
				
			

下記をseederに追記。

				
					
use Illuminate\Support\Facades\DB;

DB::table('skills')->insert([
    ['skill_name' => 'PHP',  'skill_status' => 1],
    ['skill_name' => 'Laravel',  'skill_status' => 2],
    ['skill_name' => 'JavaScript', 'skill_status' => 3],
]);
				
			

6.データベースシーダーを実行する

				
					
$ sail php artisan db:seed --class=SkillSeeder
				
			
				
					
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateSkillsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('skills', function (Blueprint $table) {
            $table->id();
            $table->string('skill_name');
            $table->integer('skill_status');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('skills');
    }
}

				
			
				
					
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class SkillSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('skills')->insert([
            ['skill_name' => 'PHP',  'skill_status' => 1],
            ['skill_name' => 'Laravel',  'skill_status' => 2],
            ['skill_name' => 'JavaScript', 'skill_status' => 3],
        ]);
    }
}

				
			

スキルテーブルの定数を設定する

6.データベースシーダーを実行する

				
					
const SKILL_STATUS_NOT_YET = 1;
const SKILL_STATUS_LEARNING = 2;
const SKILL_STATUS_LEARNED = 3;
const SKILL_STATUS_RELEARN = 4;
const SKILL_STATUS_MASTER = 5;

const SKILL_STATUS_NAME_NOT_YET = '未学習';
const SKILL_STATUS_NAME_LEARNING = '学習中';
const SKILL_STATUS_NAME_LEARNED = '学習済';
const SKILL_STATUS_NAME_RELEARN = '再学習';
const SKILL_STATUS_NAME_MASTER = 'マスター';

const SKILL_STATUS_OBJECT = [
    self::SKILL_STATUS_NOT_YET  => self::SKILL_STATUS_NAME_NOT_YET,
    self::SKILL_STATUS_LEARNING => self::SKILL_STATUS_NAME_LEARNING,
    self::SKILL_STATUS_LEARNED  => self::SKILL_STATUS_NAME_LEARNED,
    self::SKILL_STATUS_RELEARN  => self::SKILL_STATUS_NAME_RELEARN,
    self::SKILL_STATUS_MASTER   => self::SKILL_STATUS_NAME_MASTER,
];
				
			

スキルデータの表示【Read】

1.ログインしているユーザは、skill配下を閲覧できるようにする。

				
					
Route::middleware(['auth'])->prefix('skill')->group(function () {
    Route::get('/', [SkillController::class, 'index'])->name('skill');
});
				
			

2.dashboard.blade.phpを元に、skill/index.blade.phpファイルを作成する。
skillディレクトリは自分で作成する。

3.ExampleController.phpを元にSkillController.phpをコピーして作る

4.layouts/navigation.blade.phpにスキルを追加する。

5.tailwindcssのtable-layoutのページからテーブルのサンプルをとってきて、skill/index.blade.phpに設定する。

6.テーブルに@foreachでSkillsテーブルの値を表示させる

■補足
・tailwindcss
テーブル
https://tailwindcss.jp/docs/table-layout

Form
https://v1.tailwindcss.com/components/forms

下記を元に気に入ったものを利用する
https://tailblocks.cc/

				
					
@foreachは、処理を繰り返します。
@foreach($skills as $skill)
  {{ $skill }}
@endforeach
				
			
				
					
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight"><span class="ez-toc-section" id="%E3%82%B9%E3%82%AD%E3%83%AB"></span>
            スキル
        <span class="ez-toc-section-end"></span></h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-200">
                    <button onclick="location.href='/skill/new'" class="shadow bg-blue-500 hover:bg-blue-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                        新規作成
                    </button>
                        <table class="table-auto">
                            <thead>
                            <tr>
                                <th class="px-4 py-2">ID</th>
                                <th class="px-4 py-2">スキル名</th>
                                <th class="px-4 py-2">ステータス</th>
                                <th class="px-4 py-2"></th>
                            </tr>
                            </thead>
                            <tbody>
                            @foreach($skills as $skill)
                                <tr>
                                    <td class="border px-4 py-2">{{ $skill->id }}</td>
                                    <td class="border px-4 py-2">{{ $skill->skill_name }}</td>
                                    <td class="border px-4 py-2">{{ \App\Models\Skill::SKILL_STATUS_OBJECT[$skill->skill_status] }}</td>
                                    <td class="border px-4 py-2">
                                        <button onclick="location.href='/skill/detail/{{ $skill->id }}'" class="shadow bg-yellow-500 hover:bg-yellow-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                                            詳細
                                        </button>
                                    </td>
                                </tr>
                            @endforeach
                            </tbody>
                        </table>
                    <div class="flex justify-center mt-3">
                        {{ $skills->links() }}
                    </div>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

				
			

スキルデータの表示【ページネーション】

1.SkillContorllerでpaginateを指定する。

				
					
$skills = Skill::paginate(2);
				
			

2.skill/index.blade.phpに下記を追加する

				
					
<div class="flex justify-center mt-3">
    {{ $skills->links() }}
</div>
				
			

https://readouble.com/laravel/8.x/ja/pagination.html
ペジネーションビューのカスタマイズ

sail php artisan vendor:publish –tag=laravel-pagination

スキルデータの表示【詳細ページ】

1.tailwindcssのformをコピーして、skill/detail.blade.phpを作成する
https://v1.tailwindcss.com/components/forms


■補足
・tailwindcss

Form
https://v1.tailwindcss.com/components/forms

ボタン(button)
https://v1.tailwindcss.com/components/buttons#app

詳細:青
変更:オレンジ
削除:赤
戻る:グレー


下記を元に気に入ったものを利用してもいい。
https://tailblocks.cc/

・センターによせたい
flex justify-center

				
					
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight"><span class="ez-toc-section" id="%E3%82%B9%E3%82%AD%E3%83%AB-2"></span>
            スキル
        <span class="ez-toc-section-end"></span></h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-200 flex justify-center">

                    <form class="w-full max-w-sm">
                        <div class="md:flex md:items-center mb-6">
                            <div class="md:w-1/3">
                                <label class="block text-gray-500 font-bold md:text-left mb-1 md:mb-0 pr-4" for="inline-full-name">
                                    ID
                                </label>
                            </div>
                            <div class="md:w-2/3">
                                {{ $skill->id }}
                            </div>
                        </div>
                        <div class="md:flex md:items-center mb-6">
                            <div class="md:w-1/3">
                                <label class="block text-gray-500 font-bold md:text-left mb-1 md:mb-0 pr-4" for="inline-full-name">
                                    スキル名
                                </label>
                            </div>
                            <div class="md:w-2/3">
                                {{ $skill->skill_name }}
                            </div>
                        </div>
                        <div class="md:flex md:items-center mb-6">
                            <div class="md:w-1/3">
                                <label class="block text-gray-500 font-bold md:text-left mb-1 md:mb-0 pr-4" for="inline-password">
                                    ステータス
                                </label>
                            </div>
                            <div class="md:w-2/3">
                                {{ \App\Models\Skill::SKILL_STATUS_OBJECT[$skill->skill_status] }}
                            </div>
                        </div>
                        <div class="md:flex md:items-center">
                            <div class="md:w-2/3">
                                <button onclick="location.href='/skill'" class="shadow bg-gray-500 hover:bg-gray-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                                    戻る
                                </button>
                                <button onclick="location.href='/skill/edit/{{ $skill->id }}'" class="shadow bg-yellow-500 hover:bg-yellow-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                                    更新ページへ
                                </button>
                            </div>
                        </div>
                    </form>

                </div>
            </div>
        </div>
    </div>
</x-app-layout>

				
			

スキルデータの作成【Create】

1.ルーティング
web.phpにnewを追加する

2.コントローラー
SkillController.phpのnewを追加する。

3.view
new.blade.phpをdetail.blade.phpから追加する。

4.ルーティング
web.phpにcreateを追加する

5.コントローラー
SkillController.phpにcreateを追加する。

				
					
<?php

use App\Http\Controllers\SkillController;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

Route::middleware(['auth'])->prefix('skill')->group(function() {
    Route::get('/', [SkillController::class, 'index'])->name('skill');
    Route::get('/detail/{id}', [SkillController::class, 'detail'])->name('skill.detail');
    Route::get('/new', [SkillController::class, 'new'])->name('skill.new');
    Route::post('/create', [SkillController::class, 'create'])->name('skill.create');
});

require __DIR__.'/auth.php';

				
			
				
					
<?php

namespace App\Http\Controllers;

use App\Models\Skill;
use Illuminate\Http\Request;

class SkillController extends Controller
{
    //
    public function index()
    {
        $skills = Skill::paginate(15);
        return view('skill.index', [
            'skills' => $skills
        ]);
    }

    public function detail($id)
    {
        $skill = Skill::find($id);
        return view('skill.detail', [
            'skill' => $skill
        ]);
    }

    public function new()
    {
        return view('skill.new');
    }

    public function create(Request $request)
    {
        $skill = new Skill();
        $skill->skill_name = $request->input('skill_name');
        $skill->skill_status = $request->input('skill_status');
        $skill->save();

        return redirect('skill');
    }
}

				
			
				
					
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight"><span class="ez-toc-section" id="%E3%82%B9%E3%82%AD%E3%83%AB-3"></span>
            スキル
        <span class="ez-toc-section-end"></span></h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-200">
                    <button onclick="location.href='/skill/new'" class="shadow bg-blue-500 hover:bg-blue-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                        新規作成
                    </button>
                        <table class="table-auto">
                            <thead>
                            <tr>
                                <th class="px-4 py-2">ID</th>
                                <th class="px-4 py-2">スキル名</th>
                                <th class="px-4 py-2">ステータス</th>
                                <th class="px-4 py-2"></th>
                            </tr>
                            </thead>
                            <tbody>
                            @foreach($skills as $skill)
                                <tr>
                                    <td class="border px-4 py-2">{{ $skill->id }}</td>
                                    <td class="border px-4 py-2">{{ $skill->skill_name }}</td>
                                    <td class="border px-4 py-2">{{ \App\Models\Skill::SKILL_STATUS_OBJECT[$skill->skill_status] }}</td>
                                    <td class="border px-4 py-2">
                                        <button onclick="location.href='/skill/detail/{{ $skill->id }}'" class="shadow bg-yellow-500 hover:bg-yellow-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                                            詳細
                                        </button>
                                    </td>
                                </tr>
                            @endforeach
                            </tbody>
                        </table>
                    <div class="flex justify-center mt-3">
                        {{ $skills->links() }}
                    </div>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>


				
			
				
					
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight"><span class="ez-toc-section" id="%E3%82%B9%E3%82%AD%E3%83%AB%E6%96%B0%E8%A6%8F%E7%99%BB%E9%8C%B2"></span>
            スキル新規登録
        <span class="ez-toc-section-end"></span></h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-200 flex justify-center">

                    <form class="w-full max-w-sm" action="/skill/create" method="POST">
                        @csrf
                        <div class="md:flex md:items-center mb-6">
                            <div class="md:w-1/3">
                                <label class="block text-gray-500 font-bold md:text-left mb-1 md:mb-0 pr-4" for="inline-full-name">
                                    スキル名
                                </label>
                            </div>
                            <div class="md:w-2/3">
                                <input required name="skill_name" class="appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" id="inline-full-name" type="text" value="">
                            </div>
                        </div>
                        <div class="md:flex md:items-center mb-6">
                            <div class="md:w-1/3">
                                <label class="block text-gray-500 font-bold md:text-left mb-1 md:mb-0 pr-4" for="inline-password">
                                    ステータス
                                </label>
                            </div>
                            <div class="md:w-2/3">
                                <select name="skill_status" class="appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" id="inline-full-name">
                                    @foreach(\App\Models\Skill::SKILL_STATUS_OBJECT as $key => $skillName)
                                        <option value="{{ $key }}">{{$skillName}}</option>
                                    @endforeach
                                </select>
                            </div>
                        </div>
                        <div class="md:flex md:items-center">
                            <div class="md:w-2/3">
                                <button onclick="location.href='/skill'" class="shadow bg-gray-500 hover:bg-gray-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                                    戻る
                                </button>
                                <button type="submit" class="shadow bg-blue-500 hover:bg-blue-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">
                                    登録
                                </button>
                            </div>
                        </div>
                    </form>

                </div>
            </div>
        </div>
    </div>
</x-app-layout>

				
			

スキルデータの表示【フラッシュメッセージ】

1. tailwindcss flass messageでgoogle検索する

vuejsを入れる

				
					
$ sail composer require laravel/ui -- 下のコマンドを使うために実行する
$ sail php artisan ui vue -- このコマンドでvuejsがインストールされる

$ sail npm install
$ sail npm run dev

				
			

webpackがsassになってしまった。

				
					
mix.js('resources/js/app.js', 'public/js')
    .vue()
    // .sass('resources/sass/app.scss', 'public/css');
    .postCss('resources/css/app.css', 'public/css', [
        require('postcss-import'),
        require('tailwindcss'),
        require('autoprefixer'),
    ]);

->with('status', 'スキルを作成しました。');



@if(session('status'))
    <div class="bg-blue-100 border border-blue-400 text-blue-700 px-4 py-3 rounded relative" role="alert">
        <span class="block sm:inline">{{ session('status') }}</span>
        <span class="absolute top-0 bottom-0 right-0 px-4 py-3">
            <svg class="fill-current h-6 w-6 text-blue-500" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>Close</title><path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"/></svg>
          </span>
    </div>
@endif
				
			

スキルデータの表示【フラッシュメッセージ】

1.vueをインストールする

				
					
$ sail composer require laravel/ui
$ sail php artisan ui vue
				
			

2.tailwindcssがうまく表示されない場合は、下記をwebpack.mix.jsに上書き貼り付けしてください。
sail php artisan ui vueコマンドを実行すると、webpack.mix.jsファイルが上書きされてしまうようです。

				
					
const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js')
    .vue()
    // .sass('resources/sass/app.scss', 'public/css');
    .postCss('resources/css/app.css', 'public/css', [
        require('postcss-import'),
        require('tailwindcss'),
        require('autoprefixer'),
    ]);

				
			

3.webpack.mix.jsで設定した内容を反映させるために、下記コマンドを実行します。

				
					
sail npm run dev
				
			

もし、下記のようなメッセージが表示されたら、
Additional dependencies must be installed. This will only take a moment.
Running: npm install vue-loader@^15.9.7 –save-dev –legacy-peer-deps
Finished. Please run Mix again.

上記のRunningの箇所にあるように、下記コマンドを実行してみてから、再度「sail npm run dev」を実行してみてください。

				
					
$ sail npm install vue-loader@^15.9.7 --save-dev --legacy-peer-deps
				
			

スキルデータの更新【Update】

				
					
<?php

use App\Http\Controllers\SkillController;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

Route::middleware(['auth'])->prefix('skill')->group(function() {
    Route::get('/', [SkillController::class, 'index'])->name('skill');
    Route::get('/detail/{id}', [SkillController::class, 'detail'])->name('skill.detail');
    Route::get('/new', [SkillController::class, 'new'])->name('skill.new');
    Route::get('/edit/{id}', [SkillController::class, 'edit'])->name('skill.edit');

    Route::post('/create', [SkillController::class, 'create'])->name('skill.create');
    Route::patch('/update', [SkillController::class, 'update'])->name('skill.update');
});

require __DIR__.'/auth.php';

				
			
				
					
<?php

namespace App\Http\Controllers;

use App\Models\Skill;
use Illuminate\Http\Request;

class SkillController extends Controller
{
    //
    public function index()
    {
        $skills = Skill::paginate(15);
        return view('skill.index', [
            'skills' => $skills
        ]);
    }

    public function detail($id)
    {
        $skill = Skill::find($id);
        return view('skill.detail', [
            'skill' => $skill
        ]);
    }

    public function new()
    {
        return view('skill.new');
    }

    public function create(Request $request)
    {
        $skill = new Skill();
        $skill->skill_name = $request->input('skill_name');
        $skill->skill_status = $request->input('skill_status');
        $skill->save();

        return redirect('skill')->with('status', 'スキルを作成しました。');
    }

    public function edit($id)
    {
        $skill = Skill::find($id);
        return view('skill.edit', [
            'skill' => $skill
        ]);
    }

    public function update(Request $request)
    {
        $skill = Skill::find($request->input('id'));
        $skill->skill_name = $request->input('skill_name');
        $skill->skill_status = $request->input('skill_status');
        $skill->save();

        return redirect('skill')->with('status', 'スキルを更新しました。');
    }
}

				
			
				
					
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight"><span class="ez-toc-section" id="%E3%82%B9%E3%82%AD%E3%83%AB-4"></span>
            スキル
        <span class="ez-toc-section-end"></span></h2>
    </x-slot>

    <div id="app">
    @if(session('status'))
        <flash-message-component session="{{ session('status') }}"></flash-message-component>
    @endif

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-200">
                    <button onclick="location.href='/skill/new'" class="shadow bg-blue-500 hover:bg-blue-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                        新規作成
                    </button>
                        <table class="table-auto">
                            <thead>
                            <tr>
                                <th class="px-4 py-2">ID</th>
                                <th class="px-4 py-2">スキル名</th>
                                <th class="px-4 py-2">ステータス</th>
                                <th class="px-4 py-2"></th>
                                <th class="px-4 py-2"></th>
                            </tr>
                            </thead>
                            <tbody>
                            @foreach($skills as $skill)
                                <tr>
                                    <td class="border px-4 py-2">{{ $skill->id }}</td>
                                    <td class="border px-4 py-2">{{ $skill->skill_name }}</td>
                                    <td class="border px-4 py-2">{{ \App\Models\Skill::SKILL_STATUS_OBJECT[$skill->skill_status] }}</td>
                                    <td class="border px-4 py-2">
                                        <button onclick="location.href='/skill/detail/{{ $skill->id }}'" class="shadow bg-gray-500 hover:bg-gray-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                                            詳細
                                        </button>
                                    </td>
                                    <td class="border px-4 py-2">
                                        <button onclick="location.href='/skill/edit/{{ $skill->id }}'" class="shadow bg-yellow-500 hover:bg-yellow-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                                            編集
                                        </button>
                                    </td>
                                </tr>
                            @endforeach
                            </tbody>
                        </table>
                    <div class="flex justify-center mt-3">
                        {{ $skills->links() }}
                    </div>
                </div>
            </div>
        </div>
    </div>
    </div>
</x-app-layout>

				
			
				
					
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight"><span class="ez-toc-section" id="%E3%82%B9%E3%82%AD%E3%83%AB-5"></span>
            スキル
        <span class="ez-toc-section-end"></span></h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-200 flex justify-center">

                    <form class="w-full max-w-sm" action="/skill/update" method="POST">
                        @csrf
                        @method('PATCH')
                        <input value="{{ $skill->id }}" name="id" type="hidden">
                        <div class="md:flex md:items-center mb-6">
                            <div class="md:w-1/3">
                                <label class="block text-gray-500 font-bold md:text-left mb-1 md:mb-0 pr-4" for="inline-full-name">
                                    ID
                                </label>
                            </div>
                            <div class="md:w-2/3">
                                {{ $skill->id }}
                            </div>
                        </div>
                        <div class="md:flex md:items-center mb-6">
                            <div class="md:w-1/3">
                                <label class="block text-gray-500 font-bold md:text-left mb-1 md:mb-0 pr-4" for="inline-full-name">
                                    スキル名
                                </label>
                            </div>
                            <div class="md:w-2/3">
                                <input value="{{ $skill->skill_name }}" required name="skill_name" class="appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" id="inline-full-name" type="text">
                            </div>
                        </div>
                        <div class="md:flex md:items-center mb-6">
                            <div class="md:w-1/3">
                                <label class="block text-gray-500 font-bold md:text-left mb-1 md:mb-0 pr-4" for="inline-password">
                                    ステータス
                                </label>
                            </div>
                            <div class="md:w-2/3">
                                <select name="skill_status" class="appearance-none border-2 border-gray-200 rounded w-full py-2 px-4 text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-purple-500" id="inline-full-name">
                                    @foreach(\App\Models\Skill::SKILL_STATUS_OBJECT as $key => $skillName)
                                        <option value="{{ $key }}" @if($key === $skill->skill_status) selected @endif>{{$skillName}}</option>
                                    @endforeach
                                </select>
                            </div>
                        </div>
                        <div class="md:flex md:items-center">
                            <div class="md:w-2/3">
                                <button onclick="location.href='/skill'" class="shadow bg-gray-500 hover:bg-gray-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded" type="button">
                                    戻る
                                </button>
                                <button type="submit" class="shadow bg-yellow-500 hover:bg-yellow-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">
                                    更新
                                </button>
                            </div>
                        </div>
                    </form>

                </div>
            </div>
        </div>
    </div>
</x-app-layout>