Search code examples
jqueryajaxlaravel

Laravel Ajax Delete: 405 Error - Method Not Allowed


I know there are several posts about 405 Errors from using AJAX delete. However, none of the solutions from the posts I found worked for me.

I have a view with a table displaying all the machines from my database's Machine table. On each row there is a delete button to delete the machine like so:

<button class="btn btn-small btn-danger delete-machine"
    type="button"
    title="Delete Machine"
    machine-id="{{ $value->machineId }}">
    <span class="glyphicon glyphicon-trash"></span> 
</button>

On button click, the following javascript executes which calls the destroy method in the controller to delete the machine from the database:

$(document).on('click', ".delete-machine", function() {
    let button = $(this);
    let id = $(this).attr('machine-id');
    let tr = $(this).closest('tr');
    let didConfirm = confirm("Are you sure you want to permanently delete this machine?");

    if (didConfirm) {
        $.ajax({
            type: 'DELETE',
            url: 'machines/' + id,
            data: {
                '_token' : $('input[name="_token"]').val(),
                'id' : id
            },
            success: function(response) {
                if (response.didSucceed) {
                    tr.remove();

                    let flashMessage = '<div class="alert alert-success alert-block"><button type="button" class="close" data-dismiss="alert">×</button><strong>'
                        + response.message + 
                        '</strong></div>';
                    $('#flash-message').append(flashMessage);
                } else {
                    let flashMessage = '<div class="alert alert-error alert-block"><button type="button" class="close" data-dismiss="alert">×</button><strong>'
                        + response.message + 
                        '</strong></div>';
                    $('#flash-message').append(flashMessage);
                }
            },
            error: function (response) {
                console.log('Error:', response);             
            }
        });
    }
});

My controller is a resource controller. Here is the route:

Route::resource('machines', 'Machine\MachineController');

Here is the destroy method from the controller being called. It first deletes all the rows referencing the machine from a user subscription table. Then, it deletes the machine:

public function destroy($id)
{
    $userMachineSubscriptions = UserMachineSubscription::where('machine_id', $id)->get();

    foreach($userMachineSubscriptions as $userMachineSubscription) {
        $userMachineSubscription->delete();
    }

    $userMachineSubscriptions = UserMachineSubscription::where('machine_id', $id)->count();

    if ($userMachineSubscriptions <= 0) {
        $machine = Machine::find($id);

        if ($machine->delete()) {
            $message = 'Machine "' . $machine['name'] . '" successfully deleted!';
            return response()->json(['didSucceed' => 'true', 'message' => $message]);
        } else {
            $message = 'Machine "' . $machine['name'] . '" was not deleted.';
            return response()->json(['didSucceed' => 'false', 'message' => $message]);
        }
    } else {
        $message = 'Error performing cascading delete on user subscriptions. Machine was not deleted.';
        return response()->json(['didSucceed' => 'false', 'message' => $message]);
    }
}

When I run php artisan route:list, I see my route:

Method: DELETE
URI: machines/{machine}
Middleware: web, auth
Name: machines.destroy
Action: App\Http\Controllers\Machine\MachineController@destroy

What am I doing wrong? Using Laravel 5.4.

...

Also, on a side note, I am new to web-development so if anyone sees anything in my code that can be improved someway, I am open to learning :) For example, I kind of dislike my method of showing a flash message on success. I do this for several ajax requests and wish I could just do session::flash or something instead of appending the html to a div in my master blade layout. However, I can't seem to find a better way to do it.

UDPATE: Solved. Just needed to clear the route cache. :(


Solution

  • php artisan route:list
    

    See, If the DELETE request you are trying to send is allowed in the routes or not. You can also try to php artisan route:clear to clear the route cache.