Laravel9.x 使用 Tailwind CSS 进行 CRUD 练习
hi,我是温新,一名PHPer
克服恐惧,才能勇往直前
缘起。Laravel9.2 已经使用 Vite 进行前端的开发构建了。Laravel9官方文档中已经移除了Laravel Mix的相关介绍了。进行多了一个
laravel/breeze
。默认使用blade
模板,而css
则默认成了Tailwind CSS
。
Tailwind CSS
之前就有听说过,也看过,但是没有去使用过了。前端开发已经发生了翻天覆地的变化,这些变化进行影响到了后端的开发。
今天重新浏览了下 Tailwind CSS
并进行了下体验。下面使用 Laravel9
与 Tailwind CSS
来做一个小小的关于文章的 CRUD
功能。
第一步:安装 Laravel 项目
composer create-project laravel/laravel blog
第二步:配置数据库 .env
// .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=blog
DB_PASSWORD=blog
第三步:Install Breeze For Tailwind CSS
安装 laravel/breeze
composer require laravel/breeze --dev
执行安装
php artisan breeze:install
安装依赖
npm install && npm run dev
注意哦~,使用 breeze 会自动安装 auth 系统
npm run dev 后需要重新开一个窗口或终端本次运行,然后执行 migrate
执行迁移文件
php artisan migrate
第四步:创建资源路由
// routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth'])->name('dashboard');
require __DIR__.'/auth.php';
Route::resource('posts',PostController::class);
第五步:创建 Post 控制器、模型、迁移文件
# 创建控制器、模型、迁移文件
php artisan make:model Post -mcr
# 创建 Post 表单验证器
php artisan make:request PostRequest
编写 post
文件文件,database/migrations/2022_07_03_131143_create_posts_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->text('description');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
};
编写Post.php
模型文件,app/Models/Post.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = ['title', 'description'];
}
编写 PostRequest.php
表单验证文件,app/Http/Requests/PostRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'title' => ['required', 'min:2'],
'description' => ['required']
];
}
}
编写 PostController.php
,app/Http/Controllers/PostController.php
<?php
namespace App\Http\Controllers;
use App\Http\Requests\PostRequest;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::latest()->paginate();
return view('posts.index', compact('posts'));
}
public function create()
{
return view('posts.create');
}
public function store(PostRequest $request)
{
Post::create($request->input());
return redirect()->route('posts.index')->with('message', 'Post Created Successfully');
}
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
public function update(PostRequest $request, Post $post)
{
$post->update($request->input());
return redirect()->route('posts.index')->with('message', '更新成功');
}
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')->with('message', '删除成功');
}
}
第六步:Tailwind CSS 添加文章界面
<!-- resources/views/posts/create.php -->
<!-- 组件形式继承 layouts.app 模板 -->
<x-app-layout>
<!-- 使用带有名字为 header 的插槽, 将内容填充至组件 -->
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Dashboard') }}
</h2>
</x-slot>
<!-- 为 app 模板填充主体内容 -->
<div class="font-sans antialiased">
<div class="flex flex-col items-center min-h-screen pt-6 bg-gray-100 sm:justify-center sm:pt-0">
<div class="w-full px-16 py-20 mt-6 overflow-hidden bg-white rounded-lg lg:max-w-4xl">
<div class="mb-4">
<h1 class="font-serif text-3xl font-bold">创建文章</h1>
</div>
<div class="w-full px-6 py-4 bg-white rounded shadow-md ring-1 ring-gray-900/10">
<form method="POST" action="{{ route('posts.index') }}">
@csrf
<div>
<label class="block text-sm font-medium text-gray-700" for="title">
文章标题
</label>
<input
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm placeholder:text-gray-400 placeholder:text-right focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
type="text" name="title" placeholder="180" value="{{old('title')}}">
@error('title')
<span class="text-red-600 text-sm">
{{ $message }}
</span>
@enderror
</div>
<div class="mt-4">
<label class="block text-sm font-medium text-gray-700" for="description">
文章描述
</label>
<textarea name="description"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm placeholder:text-gray-400 placeholder:text-right focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
rows="4" placeholder="400"> {{old('description')}}</textarea>
@error('description')
<span class="text-red-600 text-sm">
{{ $message }}
</span>
@enderror
</div>
<div class="flex items-center justify-start mt-4">
<button type="submit"
class="inline-flex items-center px-6 py-2 text-sm font-semibold rounded-md text-sky-100 bg-sky-500 hover:bg-sky-700 focus:outline-none focus:border-gray-900 focus:ring ring-gray-300">
提交
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
第七步:Tailwind CSS 文章列表页面
<!-- resources/views/posts/index.blade.php -->
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="container max-w-6xl mx-auto mt-20">
<div class="mb-4">
<h1 class="font-serif text-3xl font-bold underline decoration-gray-400">文章列表</h1>
@if (session()->has('message'))
<div class="p-3 rounded bg-green-500 text-green-100 my-2">
{{ session('message') }}
</div>
@endif
<div class="flex justify-end">
<a href="{{ route('posts.create')}}"
class="px-4 py-2 rounded-md bg-sky-500 text-sky-100 hover:bg-sky-600">添加文章</a>
</div>
</div>
<div class="flex flex-col">
<div class="overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div
class="inline-block min-w-full overflow-hidden align-middle border-b border-gray-200 shadow sm:rounded-lg">
<table class="min-w-full">
<thead>
<tr>
<th
class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
ID</th>
<th
class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
文章标题</th>
<th
class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
文章描述</th>
<th
class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
创建时间</th>
<th class="px-6 py-3 text-sm text-left text-gray-500 border-b border-gray-200 bg-gray-50"
colspan="2">
操作</th>
</tr>
</thead>
<tbody class="bg-white">
@foreach ($posts as $post)
<tr>
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
<div class="flex items-center">
{{ $post->id }}
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
<div class="text-sm leading-5 text-gray-900">
{{ $post->title }}
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
{{ $post->description }}
</td>
<td
class="px-6 py-4 text-sm leading-5 text-gray-500 whitespace-no-wrap border-b border-gray-200">
<span> {{ $post->created_at }}</span>
</td>
<td
class="text-sm font-medium leading-5 text-center whitespace-no-wrap border-b border-gray-200 ">
<a href="{{ route('posts.edit', $post->id) }}"
class="text-indigo-600 hover:text-indigo-900">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg>
</a>
</td>
<td class="text-sm font-medium leading-5 whitespace-no-wrap border-b border-gray-200 ">
<form action="{{ route('posts.destroy',$post->id) }}" method="POST" onsubmit="return confirm('{{ trans('are You Sure ? ') }}');">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<button type="submit" class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6 text-red-600 hover:text-red-800 cursor-pointer" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</x-app-layout>
第八步:Tailwind CSS 文章编辑页面
<!-- resources/views/posts/edit.blade.php -->
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="font-sans antialiased">
<div class="flex flex-col items-center min-h-screen pt-6 bg-gray-100 sm:justify-center sm:pt-0">
<div class="w-full px-16 py-20 mt-6 overflow-hidden bg-white rounded-lg lg:max-w-4xl">
<div class="mb-4">
<h1 class="font-serif text-3xl font-bold">更新文章</h1>
</div>
<div class="w-full px-6 py-4 bg-white rounded shadow-md ring-1 ring-gray-900/10">
<form method="POST" action="{{ route('posts.update',$post->id) }}">
@csrf
@method('PUT')
<div>
<label class="block text-sm font-medium text-gray-700" for="title">
文章标题
</label>
<input
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm placeholder:text-gray-400 placeholder:text-right focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
type="text" name="title" placeholder="180" value="{{old('title',$post->title)}}">
@error('title')
<span class="text-red-600 text-sm">
{{ $message }}
</span>
@enderror
</div>
<div class="mt-4">
<label class="block text-sm font-medium text-gray-700" for="description">
文章描述
</label>
<textarea name="description"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm placeholder:text-gray-400 placeholder:text-right focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
rows="4" placeholder="400"> {{old('description',$post->description)}}</textarea>
@error('description')
<span class="text-red-600 text-sm">
{{ $message }}
</span>
@enderror
</div>
<div class="flex items-center justify-start mt-4">
<button type="submit"
class="inline-flex items-center px-6 py-2 text-sm font-semibold rounded-md text-sky-100 bg-sky-500 hover:bg-sky-700 focus:outline-none focus:border-gray-900 focus:ring ring-gray-300">
更新
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
就这样,一个简单的,关于 Tailwind CSS
的小练习就操作完啦!样式挺好看的,一起来玩吧!
请登录后再评论