Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Edris899's avatar

Laravel 5 Ajax delete request 405 method not allowed error

HI there,

#PC Specs:

- Ubuntu 18.04.1 LTS
- PHP 7.2.9
- Using apache2.

I am trying to remove a album or more with Laravel 5, jQuery & Ajax. That works ! The user can select one album with a checkmark or multiple albums to delete with a button.

The problem is, I get a this in the console of chrome.

DELETE http://www.test.nl.test/users/albums/home 405 (Method Not Allowed) Error: {readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}

This is my route:

 Route::delete('users/albums/destroy/{id}', 'AlbumsController@destroy')->name('users.albums.destroy');

This is the button

<div><button class='btn btn' style='background-color:#cfd8dc;' id="delete" type="submit" data-token="{{ csrf_token() }}"><i class="fas fa-trash grayText"></i></button></div>

This is the foreach loop for the album

<div class="row">
                @foreach($albums as $album)
                <div class="col-lg-2">
                    <div class="content">
                      <a id="overlay" >

                        <div class="content-overlay">
                            <div class="col-lg-2">
                                <label class="checkbox_custom">
                                    <input type="checkbox" name="checkbox_custom_a" id="{{$album->id}}">
                                    <span class="checkmark"></span>
                                </label>
                            </div>
                        </div>

                        <img href="{{route('users.albums.show',$album->id)}}" class="content-image" src="https://images.unsplash.com/photo-1433360405326-e50f909805b3?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&w=1080&fit=max&s=359e8e12304ffa04a38627a157fc3362">
                        <div class="content-details fadeIn-bottom">
                          <h3 class="content-title">{{$album->name}}</h3>
                          <p class="content-text">{{$album->description}}</p>
                        </div>
                      </a>
                    </div>
                    <br>
                </div>
              @endforeach
        </div>

This is the jQuery that I use.

$( "#delete" ).on( "click", function() {
                $("input:checkbox:checked").each(function () {
                    var $input = $( this );
                    console.log("Id: " + $input.attr("id") + " Value: " + $input.val());
                    
                    var url_id = $input.attr("id");
                    
                    $.ajax({
                        type: "delete",
                        url: '/users/albums/destroy/' + url_id,
                        data: {"id": url_id , _method: 'delete'},
                        headers: {
                            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                        },
                        success: function (data) {
                            console.log(data);
                            
                            //$("#url" + url_id).remove();
                        },
                        error: function (data) {
                            console.log('Error:', data);
                        }
                    });

                });
            });

This is the controller:

public function destroy($id){
        $album = Album::findOrFail($id);
        $count_photos = $album->photos()->count();
        //Delete the image on the public storage 
        if(Storage::delete('public/album_covers/'.$album->cover_image)){
            if($count_photos == 0){
                $album->delete();
                return redirect()->route('users.albums.home')->with('success', 'Album Deleted!');
            }
            else{
                foreach ($album->photos as $photo) {
                    $photo_id = $photo->pivot->photo_id;
                    $album->photos()->detach($photo_id);
                }
                $album->delete();
                return redirect()->route('users.photos.home')->with('success', 'Album Deleted!');
            }
        }
    }

--UPDATE--

Tried to change request type to post but I will dump the whole html body in the console. meh :(

0 likes
7 replies
Cronix's avatar

Hmm, try changing the request type to post (not the method in your data).

Edris899's avatar

Hi, I tried to change the request type to post in the ajax section as you said. But now it dumps all the html in the console of chrome.

Its posting the whole html body I think :(

Cronix's avatar
Cronix
Best Answer
Level 67

No, I think it's doing exactly what you're telling it to. Check your destroy method on what you're returning when the image gets deleted. You're doing redirects, which will probably just return the html from those urls. Return json back to your ajax request. You can only return a redirect if it's a regular page request, not an ajax request. That kind of defeats the point of using ajax if it did.

If you must redirect, return the url to redirect to in your json data, and do the redirect to that url in the success method of the ajax call.

1 like
Edris899's avatar

@Cronix Thanks I tried that. I works now without the error it also deleted the album.

This is the code that I used.

$( "#delete" ).on( "click", function() {
                $("input:checkbox:checked").each(function () {
                    var $input = $( this );
                    console.log("Id: " + $input.attr("id") + " Value: " + $input.val());
                    
                    var url_id = $input.attr("id");
                    
                    $.ajax({
                        type: "post",
                        url: '/users/albums/destroy/' + url_id,
                        data: {"id": url_id , _method: 'delete'},
                        headers: {
                            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                        },
                        success: function (data) {
                            console.log("success yes");
                            
                            //$("#url" + url_id).remove();
                        },
                        error: function (data) {
                            console.log('Error:', data);
                        }
                    });
                });
            });

This is in the controller the destroy method.

public function destroy($id){
        $album = Album::findOrFail($id);
        $count_photos = $album->photos()->count();
        //Delete the image on the public storage 
        if(Storage::delete('public/album_covers/'.$album->cover_image)){
            if($count_photos == 0){
                $album->delete();
                return redirect()->route('users.albums.home')->with('success', 'Album Deleted!');
            }
            else{
                foreach ($album->photos as $photo) {
                    $photo_id = $photo->pivot->photo_id;
                    $album->photos()->detach($photo_id);
                }
                $album->delete();
                // return redirect()->route('users.photos.home')->with('success', 'Album Deleted!');
                return ['success' => true];
            }
        }
    }

But the problem now is that the page isn't refreshing so it still shows the deleted album only to know that after refresh its gone.

And that's because of no redirect or refreshing of the page to get the new/updated albums record.

Any suggestion? BTW thanks alot for responding to my problem.

Cronix's avatar

Sure, If I'm understanding you right, give each album row an id in the view.

@foreach($albums as $album)
    <div class="col-lg-2" id="album-{{ $album->id }}">
// rest the same

then in the success method of your ajax call, remove that row with that id from the dom

success: function() {
    $('#album-' + url_id).remove();
}
yanka's avatar

Delete Request not allowed to return redirect()->route('users.photos.home')->with('success', 'Album Deleted!'); on Ajax so kindly request to change it to return response()->json($output). Which works for me !

Please or to participate in this conversation.