Hello Good Day to anyone who would see this, I am new to Laravel and currently having a minor problem that for some reason every time I delete, it would show the 405 (Method Not Allowed) in the console. The reason I considered it a minor problem since it works anyways when I refresh it.
I’m sorry if I’m bad at explaining but here’s some screenshots to hopefully clarify the situation
Error Message Triggered when I press Delete
But note that when I refresh it actually deletes that record…
I would post what I think are the relevant codes here :<
Controller:
<?php
namespace AppHttpControllers;
use AppModelsWaste;
use IlluminateHttpRequest;
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!');
}
}
Route:
use AppHttpControllersWasteController;
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');
View using it:
@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
2
Answers
in route file order is important.
first you wrote
get
than wroteresource
and the enddelete
. its wrong.and in my opinion you can use manual routing and change
delete
topost
method.otherwise if you want to use
delete
method you canto your ajax data and use
POST
method.see more: How to send a PUT/DELETE request in jQuery?
your ajax should be like this:
The console image reveals that you’re doing a
DELETE
request to/wastes
which, per your routes configuration, doesn’t exist.You do have a resource URL that accept
DELETE
requests to/wastes/{waste}
.That’s why you get a 405 on the request.