您现在的位置是:自如初>LaravelLaravel

Laravel9.x 使用 Tailwind CSS 进行 CRUD 练习

温新 2022-07-03 22:53:10 Laravel 813人已围观

简介Laravel9.x 使用 Tailwind CSS 进行 CRUD 练习。缘起。Laravel9.2 已经使用 Vite 进行前端的开发构建了。Laravel9官方文档中已经移除了Laravel Mix的相关介绍了。进行多了一个 `laravel/breeze`。默认使用 `blade`模板,而`css`则默认成了 `Tailwind CSS`。

hi,我是温新,一名PHPer


克服恐惧,才能勇往直前


缘起。Laravel9.2 已经使用 Vite 进行前端的开发构建了。Laravel9官方文档中已经移除了Laravel Mix的相关介绍了。进行多了一个 laravel/breeze。默认使用 blade模板,而css则默认成了 Tailwind CSS

Tailwind CSS之前就有听说过,也看过,但是没有去使用过了。前端开发已经发生了翻天覆地的变化,这些变化进行影响到了后端的开发。

今天重新浏览了下 Tailwind CSS 并进行了下体验。下面使用 Laravel9Tailwind 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.phpapp/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 的小练习就操作完啦!样式挺好看的,一起来玩吧!



很赞哦!(7)

文章评论

登录 注册

自如初--时间轴

QQ登录

站名:自如初

独白:向前走!向前走!

邮箱:xyhcx@foxmail.com

站点信息