Laravel 11+Inertia CRUD问题:编辑无数据、删除失效求解决
Laravel 11 + Inertia CRUD故障排查:编辑数据不显示、删除功能失效
问题现象
使用Laravel 11结合Inertia开发CRUD功能时,出现两个异常:
- 点击列表页(index.tsx)的编辑按钮后,编辑页面无法加载数据库中存储的现有数据
- 删除按钮点击后无任何反应,且
destroy和update方法无报错信息
现有代码
路由配置
Route::resource('galeri', GalleryController::class);
列表页(index.tsx)
import React from "react"; import { Link, usePage, router } from "@inertiajs/react"; import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout"; import { PageProps } from "@/types"; import { route } from 'ziggy-js'; const createPostRoute = route('galeri.create'); // 定义单条数据类型 interface Post { id: number; nama: string; deskripsi: string; image: string; } // 定义数据列表结构 interface Posts { data: Post[]; } const Index = ({ auth }: PageProps) => { const { posts } = usePage<{ posts: Posts; auth: PageProps["auth"] }>().props; const data: Post[] = posts.data; console.log(data); // 删除操作处理函数 const handleDelete = (id: number) => { if (confirm("Are you sure you want to delete this post?")) { router.delete(route("galeri.destroy", id)); } }; return ( <AuthenticatedLayout header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Dashboard</h2>} > <div className="container mx-auto max-w-7xl mt-4"> <h1 className="mb-8 text-4xl font-bold text-center">Posts Index</h1> <div className="flex items-center justify-between mb-6"> <Link className="px-3 py-1.5 text-white bg-blue-500 rounded-md focus:outline-none" href={route("galeri.create")} > Create Post </Link> </div> <div className="overflow-x-auto"> <table className="min-w-full bg-white"> <thead> <tr> <th className="px-4 py-2 bg-gray-200 text-gray-600 border-b border-gray-300 text-left text-sm uppercase font-semibold"> # </th> <th className="px-4 py-2 bg-gray-200 text-gray-600 border-b border-gray-300 text-left text-sm uppercase font-semibold"> Nama </th> <th className="px-4 py-2 bg-gray-200 text-gray-600 border-b border-gray-300 text-left text-sm uppercase font-semibold"> deskripsi </th> <th className="px-4 py-2 bg-gray-200 text-gray-600 border-b border-gray-300 text-left text-sm uppercase font-semibold"> image </th> <th className="px-4 py-2 bg-gray-200 text-gray-600 border-b border-gray-300 text-left text-sm uppercase font-semibold"> Actions </th> </tr> </thead> <tbody> {data && data.length > 0 ? ( data.map(({ id, nama, deskripsi, image }) => ( <tr key={id}> <td className="px-4 py-2 border-b border-gray-300">{id}</td> <td className="px-4 py-2 border-b border-gray-300">{nama}</td> <td className="px-4 py-2 border-b border-gray-300">{deskripsi}</td> <td className="px-4 py-2 border-b border-gray-300"> <img src={`/storage/${image}`} alt={nama} className="h-20 w-20 object-cover rounded" /> </td> <td className="px-4 py-2 border-b border-gray-300"> <Link className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded text-xs mr-1" href={route("galeri.edit", id)} > Edit </Link> <button className="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-2 rounded text-xs" onClick={() => handleDelete(id)} > Delete </button> </td> </tr> )) ) : ( <tr> <td className="px-4 py-2 border-b border-gray-300" colSpan={5}> No posts found. </td> </tr> )} </tbody> </table> </div> </div> </AuthenticatedLayout> ); }; export default Index;
GalleryController.php
<?php namespace App\Http\Controllers; use App\Http\Requests\StoreGalleryRequest; use App\Models\Gallery; use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; use Illuminate\Support\Facades\Redirect; use Inertia\Inertia; class GalleryController extends Controller { /** * 展示数据列表 */ public function index() { $postgaleris = Gallery::all(); return Inertia::render('Gallery/index', [ 'auth' => [ 'user' => [ 'name' => Auth::user()->name, 'email' => Auth::user()->email, ], ], 'posts' => ['data' => $postgaleris], ]); } /** * 展示创建表单 */ public function create() { return Inertia::render('Gallery/post'); } /** * 存储新数据 */ public function store(StoreGalleryRequest $request) { $data = $request->validated(); if ($request->hasFile('image')) { $imagePath = $request->file('image')->store('gallery_fotos', 'public'); $data['image'] = $imagePath; } else { $data['image'] = null; } Gallery::create($data); return Redirect::route('galeri.index'); } /** * 展示单条数据 */ public function show(Gallery $gallery) { // } /** * 展示编辑表单 */ public function edit(Gallery $gallery) { return Inertia::render('Gallery/edit', [ 'post' => [ 'id' => $gallery->id, 'nama' => $gallery->nama, 'deskripsi' => $gallery->deskripsi, 'image' => $gallery->image ? asset('storage/' . $gallery->image) : null, ], ]); } /** * 更新数据 */ public function update(StoreGalleryRequest $request, Gallery $gallery) { $data = $request->validated(); if ($request->hasFile('image')) { if ($gallery->image && \Storage::disk('public')->exists($gallery->image)) { \Storage::disk('public')->delete($gallery->image); } $data['image'] = $request->file('image')->store('gallery_fotos', 'public'); } $gallery->update($data); return Redirect::route('galeri.index'); } /** * 删除数据 */ public function destroy(Gallery $gallery) { $gallery->delete(); return Redirect::route('galeri.index'); } }
故障排查与修复方案
1. 编辑页面数据不显示问题
核心原因
编辑页面(Gallery/edit.tsx)未正确接收并使用Controller传递的post数据
修复步骤
确保edit.tsx通过usePage正确获取并渲染数据,示例代码如下:
// Gallery/edit.tsx import React from "react"; import { usePage, router } from "@inertiajs/react"; import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout"; import { route } from 'ziggy-js'; interface Post { id: number; nama: string; deskripsi: string; image: string | null; } const Edit = () => { const { post } = usePage<{ post: Post }>().props; return ( <AuthenticatedLayout header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Edit Post</h2>}> <div className="container mx-auto max-w-7xl mt-4"> <form onSubmit={(e) => { e.preventDefault(); const formData = new FormData(e.target as HTMLFormElement); router.put(route("galeri.update", post.id), formData, { onError: (errors) => console.error('更新失败:', errors) }); }} > <div className="mb-4"> <label className="block mb-2 text-sm font-medium text-gray-700">Nama</label> <input type="text" name="nama" defaultValue={post.nama} className="w-full border-gray-300 rounded-md shadow-sm focus:border-blue-500 focus:ring-blue-500" required /> </div> <div className="mb-4"> <label className="block mb-2 text-sm font-medium text-gray-700">Deskripsi</label> <textarea name="deskripsi" defaultValue={post.deskripsi} className="w-full border-gray-300 rounded-md shadow-sm focus:border-blue-500 focus:ring-blue-500" rows={4} required ></textarea> </div> {post.image && ( <div className="mb-4"> <p className="mb-2 text-sm font-medium text-gray-700">当前图片</p> <img src={post.image} alt={post.nama} className="h-24 w-24 object-cover rounded-md" /> </div> )} <div className="mb-6"> <label className="block mb-2 text-sm font-medium text-gray-700">更换图片</label> <input type="file" name="image" className="w-full border-gray-300 rounded-md shadow-sm focus:border-blue-500 focus:ring-blue-500" accept="image/*" /> </div> <div className="flex gap-2"> <button type="submit" className="px-4 py-2 text-white bg-blue-600 rounded-md hover:bg-blue-700" > 更新数据 </button> <Link href={route("galeri.index")} className="px-4 py-2 text-gray-700 bg-gray-200 rounded-md hover:bg-gray-300" > 返回列表 </Link> </div> </form> </div> </AuthenticatedLayout> ); }; export default Edit;
2. 删除功能失效问题
核心原因
Inertia的router.delete未配置回调,且未处理可能的请求失败场景
修复步骤
修改index.tsx中的handleDelete函数,添加请求回调并确保CSRF令牌正常携带:
const handleDelete = (id: number) => { if (confirm("确定要删除这条数据吗?")) { router.delete(route("galeri.destroy", id), { onSuccess: () => { // 删除成功后刷新页面 router.reload(); }, onError: (errors) => { console.error('删除失败:', errors); alert('删除失败,请稍后重试'); } }); } };
同时确认HandleInertiaRequests中间件已共享CSRF令牌:
// app/Http/Middleware/HandleInertiaRequests.php public function share(Request $request): array { return array_merge(parent::share($request), [ 'csrf_token' => csrf_token(), // 其他共享数据 ]); }
3. 额外检查点
- 运行
php artisan route:list确认galeri.destroy和galeri.edit路由存在,参数名正确 - 检查
StoreGalleryRequest的验证规则,确保更新时允许图片字段为空:public function rules() { return [ 'nama' => 'required|string|max:255', 'deskripsi' => 'required|string', 'image' => 'nullable|image|max:2048', ]; } - 打开浏览器开发者工具,查看Network标签下的DELETE/PUT请求状态,确认请求是否正常发送
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

