博客项目 laravel vue mysql 第五章 标签功能

前言

前面章节没看过的朋友请先从第一章开始看 。这章主要写标签相关功能。

后端

创建迁移文件

php artisan make:migration create_tags_table

编辑迁移文件

public function up()
{
    Schema::create('tags', function (Blueprint $table) {
        $table->id(); // 主键,自增ID
        $table->string('name')->unique(); // 标签名称,唯一,如“Laravel”
        $table->string('slug')->unique(); // 标签别名,URL 友好,如“laravel”
        $table->timestamps(); // 创建时间和更新时间
    });
}

运行迁移

php artisan migrate

编辑种子文件database/seeders/DatabaseSeeder.php

// 创建8个标签
use App\Models\Tag;

$tags = [
    Tag::create(['name' => 'Laravel', 'slug' => 'laravel']),
    Tag::create(['name' => 'Vue.js', 'slug' => 'vue']),
    Tag::create(['name' => 'PHP', 'slug' => 'php']),
    Tag::create(['name' => 'JavaScript', 'slug' => 'javascript']),
    Tag::create(['name' => 'MySQL', 'slug' => 'mysql']),
    Tag::create(['name' => 'CSS', 'slug' => 'css']),
    Tag::create(['name' => 'Git', 'slug' => 'git']),
    Tag::create(['name' => 'Docker', 'slug' => 'docker']),
];

执行迁移命令,注意:先创建模型

php artisan migrate:fresh
php artisan db:seed

创建模型命令

php artisan make:model Tag

编辑文件app/Models/Tag.php

protected $fillable = ['name', 'slug'];

创建控制器命令

php artisan make:controller TagController

编辑控制器app/Http/Controller/TagController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Tag;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class TagController extends Controller
{
    public function index(Request $request)
    {
        // 验证请求参数
        $validated = $request->validate([
            'per_page' => 'integer|min:1|max:100',
            'page' => 'integer|min:1',
            'search' => 'nullable|string|max:255'
        ]);

        // 获取分页参数,设置默认值
        $perPage = $validated['per_page'] ?? 10;
        $page = $validated['page'] ?? 1;
        $search = $validated['search'] ?? null;

        // 构建查询
        $query = Tag::select('id', 'name', 'slug', 'create_at')->orderBy('create_at', 'desc');

        // 应用搜索过滤
        if($search) {
            $query->where('name', 'like', "%{$search}%");
        }

        // 执行分页查询
        $tags = $query->paginate($perPage, ['id', 'name', 'slug'], 'page', $page);

        // 返回json
        return response()->json([
            'data' => $tags->items(),
            'pagination' => [
                'total' => $tags->total(),
                'per_page' => $tags->perPage(),
                'current_page' => $tags->currentPage(),
                'last_page' => $tags->lastPage()
            ]
        ], 200);
    }

    /**
     * 创建标签
     * @param \Illuminate\Http\Request $request
     * @return mixed|\Illuminate\Http\JsonResponse
     */
    public function store(Request $request)
    {
        // 验证请求数据
        $validated = $request->validate([
            'name' => 'required|string|max:50|unique:tags,name',
            'slug' => 'nullable|string|max:255|unique:tags,slug'
        ], [
            'name.required' => '标签名不能为空',
            'name.max' => '标签名不能超过50个字符',
            'name.unique' => '标签名称已存在',
            'slug.unique' => '标签别名已存在'
        ]);

        // 自动生成slug
        $validated['slug'] = $validated['slug'] ?? Str::slug($validated['name']);

        try {
            // 创建标签
            $tag = Tag::create([
                'name' => $validated['name'],
                'slug' => $validated['slug']
            ]);

            return response()->json([
                'data' => [
                    'id' => $tag->id,
                    'name' => $tag->name,
                    'slug' => $tag->slug
                ],
                'message' => '创建标签成功'
            ], 200);
        }catch(\Exception $e) {
            return response()->json([
                'message' => '创建标签失败'. $e->getMessage()
            ], 500);
        }
    }

    /**
     * 更新标签
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\Tag $tag
     * @return mixed|\Illuminate\Http\JsonResponse
     */
    public function update(Request $request,tag $tag)
    {
        // 验证请求数据
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:50', Rule::unique('tag', 'name')]->ignore($tag->id),
            'slug' => ['required', 'string', 'max:255', Rule::unique('tags', 'slug')->ignore($tag->id)]
        ], [
            'name.required' => '标签名称不能为空',
            'name.max' => '标签名称不能超过50个字符',
            'name.unique' => '标签名称已存在',
            'slug.unique' => '标签别名已存在',
        ]);

        // 自动生成slug
        $validated['slug'] = $validated['slug'] ?? Str::slug($validated['name']);

        try {
            // 更新标签
            $tag->update([
                'name' => $validated['name'],
                'slug' => $validated['slug']
            ]);

            return response()->json([
                'data' => [
                    'id' => $tag->id,
                    'name' => $tag->name,
                    'slug' => $tag->slug
                ],
                'message' => '标签更新成功'
            ], 200);

        } catch(\Exception $e) {
            return response()->json([
                'message' => '标签更新失败'. $e->getMessage()
            ], 500);
        }

    }
    
    /**
     * 删除标签
     * @param \App\Models\Tag $tag
     * @return mixed|\Illuminate\Http\JsonResponse
     */
    public function destory(tag $tag)
    {
        try {
            $tag->delete();

            return response()->json([
                'message' => '标签删除成功'
            ], 204);

        } catch(\Exception $e){
            return response()->json([
                'message' => '标签删除失败'
            ], 500);
        }
    }
}

编辑路由文件routes/api.php

use App\Http\Controllers\TagController;

 // 标签
Route::prefix('tags')->group(function () {
    Route::get('/', [TagController::class, 'index']); // 获取标签列表
    Route::post('/', [TagController::class, 'store']); // 创建标签
    Route::put('/{tag}', [TagController::class, 'update']); // 更新标签
    Route::delete('/{tag}', [TagController::class, 'destroy']); // 删除标签
});

前端

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值