メモ > 技術 > フレームワーク: Laravel10 > 論理削除に対応したCRUDの新規作成例(分類管理を作成)
論理削除に対応したCRUDの新規作成例(分類管理を作成)
■テーブルの作成
$ sail artisan make:migration create_categories_table
以下のファイルが作成される。
database/migrations/2024_04_18_090608_create_categories_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};
以下のとおり修正する。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name')->comment('名前');
$table->integer('sort')->comment('並び順');
$table->timestamps();
$table->softDeletes();
$table->comment('分類');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};
マイグレーションを実行。
$ sail artisan migrate
■モデルの作成
$ sail artisan make:model Category
以下のファイルが作成される。
app/Models/Category.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use HasFactory;
}
以下のとおり修正する。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Category extends Model
{
use SoftDeletes;
protected $fillable = [
'name',
'sort',
];
}
■リクエストの作成
$ sail artisan make:request CategoryCreateRequest
以下のファイルが作成される。
app/Http/Requests/CategoryCreateRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CategoryCreateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
//
];
}
}
以下のとおり修正する。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CategoryCreateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:20'],
'sort' => ['required', 'integer'],
];
}
public function attributes(): array
{
return [
'name' => '名前',
'sort' => '並び順',
];
}
}
以下のファイルを作成する。
app/Http/Requests/CategoryUpdateRequest.php
<?php
namespace App\Http\Requests;
class CategoryUpdateRequest extends CategoryCreateRequest
{
}
■コントローラーの作成
$ sail artisan make:controller CategoryController
以下のファイルが作成される。
app/Http/Controllers/CategoryController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class CategoryController extends Controller
{
//
}
以下のとおり修正する。
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CategoryCreateRequest;
use App\Http\Requests\CategoryUpdateRequest;
use Illuminate\Http\RedirectResponse;
use App\Models\Category;
use Illuminate\Support\Facades\Redirect;
use Illuminate\View\View;
class CategoryController extends Controller
{
public function index(): View
{
$category = new Category;
return view('category.index', [
'categories' => $category->get(),
]);
}
public function create(): View
{
return view('category.form');
}
public function store(CategoryCreateRequest $request): RedirectResponse
{
$category = new Category;
$category->fill($request->all())->save();
return Redirect::route('category.index')->with('message', '登録しました。');
}
public function edit($id): View
{
$category = Category::findOrFail($id);
return view('category.form', [
'category' => $category,
]);
}
public function update(CategoryUpdateRequest $request, $id): RedirectResponse
{
$category = Category::findOrFail($id);
$category->fill($request->all())->save();
return Redirect::route('category.index')->with('message', '編集しました。');
}
public function destroy($id): RedirectResponse
{
$category = Category::findOrFail($id);
$category->delete();
return Redirect::route('category.index')->with('message', '削除しました。');
}
}
■ビューの作成
以下のファイルを作成する。
resources/views/category/index.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
分類
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
<div class="max-w-xl">
<section>
<header>
<h2 class="text-lg font-medium text-gray-900">
分類一覧
</h2>
<p class="mt-1 text-sm text-gray-600">
分類を管理します
</p>
</header>
@if (session('message'))
<p class="text-green-600 bg-green-100 my-4 p-4 border-l-4 border-green-400">{{ session('message') }}</p>
@elseif (session('error'))
<p class="text-red-600 bg-red-100 my-4 p-4 border-l-4 border-red-400">{{ session('error') }}</p>
@endif
<p class="my-4"><a class="underline text-gray-600 hover:text-gray-900" href="{{ route('category.create') }}">分類登録</a></p>
<table class="w-full border shadow">
<thead>
<th class="border p-2">名前</th>
<th class="border p-2">並び順</th>
<th class="border p-2">編集</th>
</thead>
<tbody>
@foreach ($categories as $category)
<tr>
<td class="border p-2"><div>{{ $category->name }}</div></td>
<td class="border p-2"><div>{{ $category->sort }}</div></td>
<td class="border p-2"><a class="underline text-gray-600 hover:text-gray-900" href="{{ route('category.edit', ['id' => $category->id]) }}">編集</a></td>
</tr>
@endforeach
</tbody>
</table>
</section>
</div>
</div>
</div>
</div>
</x-app-layout>
resources/views/category/form.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
分類
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
<div class="max-w-xl">
<section>
<header>
<h2 class="text-lg font-medium text-gray-900">
@if (Request::is('*/edit')) {{ '編集' }} @else {{ '登録' }} @endif
</h2>
<p class="mt-1 text-sm text-gray-600">
分類を管理します
</p>
</header>
<form method="post" action="{{ Request::is('category/edit/*') ? route('category.update', ['id' => $category->id]) : route('category.store') }}" class="mt-6 space-y-6">
@if (Request::is('category/edit/*'))
{{ method_field('patch') }}
@endif
{{ csrf_field() }}
<div>
<x-input-label for="name" value="名前" />
<x-text-input id="name" name="name" type="text" class="mt-1 block w-full" value="{{ old('name', isset($category) ? $category->name : '') }}" autofocus autocomplete="name" />
<x-input-error class="mt-2" :messages="$errors->get('name')" />
</div>
<div>
<x-input-label for="sort" value="並び順" />
<x-text-input id="sort" name="sort" type="text" class="mt-1 block w-full" value="{{ old('sort', isset($category) ? $category->sort : '') }}" autocomplete="sort" />
<x-input-error class="mt-2" :messages="$errors->get('sort')" />
</div>
<div class="flex items-center gap-4">
<x-primary-button>@if (!Request::is('*/create')) {{ '編集' }} @else {{ '登録' }} @endif</x-primary-button>
</div>
</form>
</section>
</div>
</div>
@if (Request::is('category/edit/*'))
<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
<div class="max-w-xl">
<section>
<header>
<h2 class="text-lg font-medium text-gray-900">
削除
</h2>
<p class="mt-1 text-sm text-gray-600">
分類を削除します
</p>
</header>
<form method="post" action="{{ route('category.destroy', ['id' => $category->id]) }}" class="mt-6 space-y-6">
{{ method_field('delete') }}
{{ csrf_field() }}
<div class="flex items-center gap-4">
<x-danger-button>削除</x-danger-button>
</div>
</form>
</section>
</div>
</div>
@endif
</div>
</div>
</x-app-layout>
■ルーティングの設定
以下のとおり設定する。
routes/web.php
use App\Http\Controllers\CategoryController;
Route::middleware('auth')->group(function () {
Route::get('/category', [CategoryController::class, 'index'])->name('category.index');
Route::get('/category/create', [CategoryController::class, 'create'])->name('category.create');
Route::post('/category/store', [CategoryController::class, 'store'])->name('category.store');
Route::get('/category/edit/{id}', [CategoryController::class, 'edit'])->name('category.edit');
Route::patch('/category/update/{id}', [CategoryController::class, 'update'])->name('category.update');
Route::delete('/category/destroy/{id}', [CategoryController::class, 'destroy'])->name('category.destroy');
■動作確認
http://laravel.local/category