Laravel删除触发405 Method Not Allowed但刷新后生效问题求助
Laravel删除操作出现405错误但记录已删除的问题
我是Laravel新手,目前遇到一个问题:每次执行删除操作时,控制台会弹出405 Method Not Allowed错误,但刷新页面后记录实际已被删除。
错误相关截图说明
- 删除触发的错误信息:显示405 Method Not Allowed状态码,请求方式为GET,目标路径为
/wastes/[记录ID] - 控制台日志:记录了GET请求返回405错误的详细信息
控制器代码
<?php namespace App\Http\Controllers; use App\Models\Waste; use Illuminate\Http\Request; class WasteController extends Controller { public function index() { $waste = Waste::all(); return view('wastes.index', compact('waste')); } public function create() { return view('wastes.create'); } public function store(Request $request) { // Validate the request $request->validate([ 'WasteID' => 'required|unique:wastes', 'WasteName' => 'required', ]); // Create Waste::create($request->all()); return redirect()->route('wastes.index')->with('success', 'Waste record created successfully!'); } public function show($id) { $waste = Waste::findOrFail($id); return view('wastes.show', compact('waste')); } public function edit($id) { $waste = Waste::findOrFail($id); return view('wastes.edit', compact('waste')); } public function update(Request $request, $id) { // Validate $request->validate([ 'WasteID' => 'required|unique:wastes,WasteID,' . $id, 'WasteName' => 'required', ]); // Update $waste = Waste::findOrFail($id); $waste->update($request->all()); return redirect()->route('wastes.index')->with('success', 'Waste record updated successfully!'); } public function destroy($id) { $waste = Waste::findOrFail($id); $waste->delete(); return redirect()->route('wastes.index')->with('success', 'Waste record deleted successfully!'); } }
路由代码
use App\Http\Controllers\WasteController; Route::get('/wastes', [WasteController::class, 'index'])->name('wastes.index'); Route::get('/wastes/create', [WasteController::class, 'create'])->name('wastes.create'); Route::resource('wastes', WasteController::class); Route::delete('/wastes/delete-selected', [WasteController::class, 'deleteSelected'])->name('wastes.deleteSelected'); Route::delete('/wastes/{waste}', [WasteController::class, 'destroy'])->name('wastes.destroy');
视图代码
@extends('layouts.app') @section('content') <h1>Waste Records</h1> @if(session('success')) <div class="alert alert-success"> {{ session('success') }} </div> @endif <div class="mb-3"> <a href="{{ route('wastes.create') }}" class="btn btn-primary">Create New Waste Record</a> <button class="btn btn-danger" onclick="deleteSelected()">Delete Selected</button> </div> <table class="table" id="wasteTable"> <thead> <tr> <th data-sort="WasteID">Select</th> <th data-sort="WasteID">Waste ID</th> <th data-sort="WasteName">Waste Name</th> <th data-sort="WasteType">Waste Type</th> <th data-sort="TimeCollected">Time Collected</th> <th data-sort="MassCollected">Mass Collected</th> <th data-sort="AreaCollected">Area Collected</th> <th data-sort="DisposalLocation">Disposal Location</th> <th data-sort="WasteCategory">Waste Category</th> <th>Other Description</th> <th>Remarks</th> <th>Actions</th> </tr> </thead> <tbody> @forelse($waste as $record) <tr> <td><input type="checkbox" name="selected[]" value="{{ $record->id }}"></td> <td>{{ $record->WasteID }}</td> <td contenteditable="false" data-id="{{ $record->id }}" data-field="WasteName" class="editable">{{ $record->WasteName }}</td> <td>{{ $record->WasteType }}</td> <td>{{ $record->TimeCollected }}</td> <td>{{ $record->MassCollected }} kg</td> <td>{{ $record->AreaCollected }}</td> <td>{{ $record->DisposalLocation }}</td> <td>{{ $record->WasteCategory }}</td> <td>{{ $record->OtherDescription }}</td> <td> @if($record->Solid) Solid, @endif @if($record->Liquid) Liquid, @endif @if($record->Biodegradable) Biodegradable, @endif @if($record->NonBiodegradable) Non-Biodegradable, @endif @if($record->Recyclable) Recyclable, @endif @if($record->Hazardous) Hazardous, @endif @if($record->Corrosive) Corrosive, @endif @if($record->Ignitable) Ignitable, @endif @if($record->Reactive) Reactive, @endif @if($record->Toxic) Toxic, @endif </td> <td> <a href="{{ route('wastes.show', $record->id) }}" class="btn btn-info btn-sm">View</a> <a href="{{ route('wastes.edit', $record->id) }}" class="btn btn-warning btn-sm">Edit</a> <button class="btn btn-danger btn-sm" onclick="deleteRecord({{ $record->id }})">Delete</button> </td> </tr> @empty <tr> <td colspan="12">No waste records found.</td> </tr> @endforelse </tbody> </table> {{-- Scripts Area --}} <script src="{{ asset('jquery-3.7.1.js') }}"></script> <script> var sortOrder = {}; $('table th').on('click', function() { var column = $(this).data('sort'); if (!sortOrder[column]) { sortOrder[column] = 'asc'; } else { sortOrder[column] = sortOrder[column] === 'asc' ? 'desc' : 'asc'; } sortTable(column, sortOrder[column]); }); function sortTable(column, order) { var rows = $('table tbody tr').get(); rows.sort(function(a, b) { var keyA = $(a).children('td').eq(getColumnIndex(column)).text(); var keyB = $(b).children('td').eq(getColumnIndex(column)).text(); if (order === 'asc') { return (keyA > keyB) ? 1 : -1; } else { return (keyA < keyB) ? 1 : -1; } }); $.each(rows, function(index, row) { $('table tbody').append(row); }); } function getColumnIndex(columnName) { var index = -1; $('table th').each(function(i) { if ($(this).data('sort') === columnName) { index = i; return false; } }); return index; } function sortTable(column, order) { var rows = $('table tbody tr').get(); rows.sort(function(a, b) { var keyA = $(a).children('td').eq(getColumnIndex(column)).text(); var keyB = $(b).children('td').eq(getColumnIndex(column)).text(); if (order === 'asc') { return (keyA > keyB) ? 1 : -1; } else { return (keyA < keyB) ? 1 : -1; } }); $.each(rows, function(index, row) { $('table tbody').append(row); }); } function getColumnIndex(columnName) { var index = -1; $('table th').each(function(i) { if ($(this).data('sort') === columnName) { index = i; return false; } }); return index; } //!! function deleteSelected() { var selectedIds = $('input[name="selected[]"]:checked').map(function(){ return $(this).val(); }).get(); if (selectedIds.length === 0) { alert('Please select at least one record to delete.'); return; } if (confirm('Are you sure you want to delete selected records?')) { $.ajax({ url: '{{ route('wastes.deleteSelected') }}', type: 'DELETE', data: { "_token": "{{ csrf_token() }}", "selectedIds": selectedIds }, success: function(response) { alert(response.message); location.reload(); }, error: function(xhr) { alert('Error deleting selected records.'); } }); } } //!! function deleteRecord(WasteID) { if (confirm('Are you sure you want to delete this record?')) { $.ajax({ url: '/wastes/' + WasteID, type: 'DELETE', data: { "_token": "{{ csrf_token() }}", }, success: function(response) { alert(response.message); location.reload(); }, error: function(xhr) { alert('Error deleting the record.'); } }); } } </script> <script> $(document).ready( function () { $('#wasteTable').DataTable(); }); </script> @endsection
问题原因及解决办法
1. 路由重复定义导致冲突
Route::resource('wastes', WasteController::class)已经自动生成了所有RESTful路由,包括index、create、destroy等。你额外手动添加的Route::get('/wastes', ...)、Route::get('/wastes/create', ...)和Route::delete('/wastes/{waste}', ...)都是重复路由,而且手动路由在resource路由之后,会导致路由匹配逻辑混乱。
解决:
修改路由文件,只保留必要的路由:
use App\Http\Controllers\WasteController; Route::resource('wastes', WasteController::class); Route::delete('/wastes/delete-selected', [WasteController::class, 'deleteSelected'])->name('wastes.deleteSelected');
2. 控制器返回值不符合AJAX请求预期
你的destroy方法返回的是页面重定向,这是给普通表单提交用的。但前端用的是AJAX请求,AJAX期望接收JSON响应,而不是重定向指令。当AJAX收到重定向响应后,会自动发起GET请求到重定向的URL,这个GET请求不符合destroy路由要求的DELETE方法,因此触发405错误。
解决:
修改控制器的destroy方法,添加缺失的deleteSelected方法,返回JSON响应:
public function destroy($id) { $waste = Waste::findOrFail($id); $waste->delete(); return response()->json(['message' => 'Waste record deleted successfully!']); } public function deleteSelected(Request $request) { Waste::whereIn('id', $request->selectedIds)->delete(); return response()->json(['message' => 'Selected records deleted successfully!']); }
3. 前端AJAX URL硬编码优化(可选)
单个删除的AJAX中,硬编码URL不够可靠,改用路由生成方式更稳妥:
function deleteRecord(id) { if (confirm('Are you sure you want to delete this record?')) { $.ajax({ url: '{{ route('wastes.destroy', ':id') }}'.replace(':id', id), type: 'DELETE', data: { "_token": "{{ csrf_token() }}", }, success: function(response) { alert(response.message); location.reload(); }, error: function(xhr) { alert('Error deleting the record.'); } }); } }
内容的提问来源于stack exchange,提问作者AverageWeebo101
相关产品推荐
相关产品推荐

