11、Laravel 11 分类 CURD
现在,我们构建一个后台管理功能,对分类进行简单的管理。作为一个很简单的小小的演示,当然不会真的像写后台那样了。
我们通过导航链接来进行模拟。
创建资源控制器与模型
$ php artisan make:controller CategoryController --resource --model=Category
- 
--resource用于创建资源控制器 - 
--model用于创建模型 
资源控制包含了 7 个方法,大家可以打开 CategoryController.php 进行查看。
创建资源路由
routes/web.php
...
    
Route::resource('categories', \App\Http\Controllers\CategoryController::class);
资源路由,一个顶 7 个,现在我们查看下路由。
$ php artisan route:list | grep categories
  GET|HEAD        categories ...................................................... categories.index › CategoryController@index
  POST            categories ...................................................... categories.store › CategoryController@store
  GET|HEAD        categories/create ............................................. categories.create › CategoryController@create
  GET|HEAD        categories/{category} ............................................. categories.show › CategoryController@show
  PUT|PATCH       categories/{category} ......................................... categories.update › CategoryController@update
  DELETE          categories/{category} ....................................... categories.destroy › CategoryController@destroy
  GET|HEAD        categories/{category}/edit ........................................ categories.edit › CategoryController@edit
这些路由的意思如下:
| 动词 | URI | 操作 | 路由名称 | 
|---|---|---|---|
| GET | /categories | 列表 | categories.index | 
| GET | /categories/create | 创建表单 | categories.create | 
| POST | /categories | 存储新记录 | categories.store | 
| GET | /categories/{category} | 显示单个记录 | categories.show | 
| GET | /categories/{category}/edit | 编辑表单 | categories.edit | 
| PUT/PATCH | /categories/{category} | 更新记录 | categories.update | 
| DELETE | /categories/{category} | 删除记录 | categories.destroy | 
分类导航
路由已经准备完成,接下来是该添加导航了。
resources/views/layouts/navigation.blade.php
...
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
    <x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
        {{ __('Dashboard') }}
    </x-nav-link>
    <a href="{{ route('categories.index') }}" class="inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out">
        分类
    </a>
</div>
...
分类列表
现在,让我们构建显示分类的实际页面。在控制器中,我们需要像在其他课程中那样做:获取所有记录并将其传递给视图。
1、获取数据
app/Http/Controllers/CategoryController.php
...
public function index()
{
    $categories = Category::all();
    return view('categories.index', compact('categories'));
}
2、模板渲染数据
resources/views/categories/index.blade.php
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Dashboard') }}
            {{ __('Categories') }}
        </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 text-gray-900">
                    {{ __("你已经登录!") }}
                    <table>
                        <thead>
                        <tr>
                            <th>分类名称</th>
                            <th></th>
                        </tr>
                        </thead>
                        <tbody>
                        @foreach($categories as $category)
                            <tr>
                                <td>{{ $category->name }}</td>
                                <td>
                                    <a href="{{ route('categories.edit', $category) }}">编辑</a>
                                </td>
                            </tr>
                        @endforeach
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>
编辑分类
点击编辑链接后,将会显示一个空白页面,因为我们尚未构建它。接下来,让我们制作编辑页面。我们必须在控制器中返回视图,并传入 category 变量。
1、编写方法
app/Http/Controllers/CategoryController.php
...
public function edit(Category $category)
{
    return view('categories.edit', compact('category'));
}
2、模板渲染
resources/views/categories/edit.blade.php
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Category Edit') }}
        </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 text-gray-900">
                    <form method="POST" action="{{ route('categories.update', $category) }}">
                        @csrf
                        @method('PUT')
                        <div>
                            <div>
                                <label for="name">分类名称:</label>
                            </div>
                            <input type="text" name="name" id="name" value="{{ $category->name }}" class="border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm">
                        </div>
                        <div>
                            <button type="submit" class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 focus:bg-gray-700 active:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition ease-in-out duration-150">
                                修改
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</x-app-layout>
- 在 form 表单中,我们使用的是 POST 方法
 - 而对于更新而言,实际使用的是 PUT 或 PATCH 方法。也就是 
@method('PUT')指定的方法 - 
@csrf用于夸站攻击保护,如何缺少它,提交表单时将报错 419 错误 
更新分类
更新操作对应的是控制器中 update 方法。
1、修改模型
app/Models/Category.php
...
protected $fillable = ['name']; 
在对模型使用 update() 或 create() 方法时,所有字段都必须作为数组添加到 $fillable 属性中。
app/Models/Post.php
...
protected $fillable = ['title', 'text', 'category_id']; 
2、更新
app/Http/Controllers/CategoryController.php
...
    
public function update(Request $request, Category $category)
{
    $category->update([
       'name'=>$request->input('name'),
    ]);
    return redirect()->route('categories.index');
}
添加分类
1、新增“添加”按钮
resources/views/categories/index.blade.php
...
<a href="{{ route('categories.create') }}" class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 focus:bg-gray-700 active:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition ease-in-out duration-150">添加分类</a>
<table>
...
</table>
...
2、添加创建页面
resources/views/categories/create.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">
        <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
            <form method="POST" action="{{ route('categories.store') }}">
                @csrf
                <div>
                    <div>
                        <label for="name">分类名称:</label>
                    </div>
                    <input type="text" name="name" id="name" class="border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm">
                </div>
                <div>
                    <button type="submit" class="inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 focus:bg-gray-700 active:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition ease-in-out duration-150">
                        添加
                    </button>
                </div>
            </form>
        </div>
    </div>
</div>
</x-app-layout>
3、添加控制器方法
app/Http/Controllers/CategoryController.php
...
public function create()
{
    return view('categories.create');
}
4、分类入库
app/Http/Controllers/CategoryController.php
...
public function store(Request $request)
{
    Category::create([
        'name' => $request->input('name'),
    ]);
    return redirect()->route('categories.index');
}
删除分类
删除的时候我们需要注意一下,这里采用 form 表单的形式进行删除。
1、添加删除按钮
resources/views/categories/index.blade.php
...
<table>
    <thead>
    <tr>
        <th>分类名称</th>
        <th></th>
    </tr>
    </thead>
    <tbody>
    @foreach($categories as $category)
        <tr>
            <td>{{ $category->name }}</td>
            <td>
                <a href="{{ route('categories.edit', $category) }}">编辑</a>
                <form method="POST" action="{{ route('categories.destroy', $category) }}">
                    @csrf
                    @method('DELETE')
                    <button type="submit" onclick="return confirm('Are you sure?')">删除</button>
                </form>
            </td>
        </tr>
    @endforeach
    </tbody>
</table>
...
2、删除
app/Http/Controllers/CategoryController.php
...
public function destroy(Category $category)
{
    $category->delete();
    return redirect()->route('categories.index');
}