warpig's avatar
Level 12

How to destroy records?

Hello guys im having a bit of a trouble understanding the @method function, especially when deleting records, heres my form request:

<form method="POST" action="/posts/{{$post->slug}}">
@csrf
@method('DELETE')
<button> <span> <i class="fas fa-skull-crossbones"></i> Delete </span> </button>
</form>

The part below is the confusing part for me, I know that when specifying a route for a controllers function, one should specify a method that the Route will follow, then use a path that will return a view, we can pass in a wildcard that needs to be included in the function as the parameter, then the controllers name with the function.

HTML Form and Route

If i look and compare both files, everything looks "okay", I got the variable im using in my function $post as well as the parameter. Ive read that theres a convention to follow when specifying the "destroy" method on our Routes, which is like the one below.

At first I thought it could be "/posts/{$slug}/destroy" but maybe you could tell me more about that if you wish.

Route::post('/posts/destroy/{slug}', 'PostsController@destroy')->middleware('auth');

At the PostsController.php file my function looks like this:

    public function destroy(Post $post, $slug)
    {
        $post = Post::findOrFail($slug);
        $post->delete();

        return redirect('posts/');
    }

Since all of functions finding had been done using the slug of the post, I am also passing it inside its parameters and im redirecting (for now) to the page where ALL the posts are shown.

This is the error thrown

Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
The DELETE method is not supported for this route. Supported methods: GET, HEAD, PUT. 
0 likes
9 replies
GeordieJackson's avatar

The route: Route::post

should be:

Route::delete

i.e. use the Route::delete method to initiate a delete request.

1 like
tinkerbell's avatar
   <button type="submit" class="btn btn-danger"
                                                onclick="return confirm('Are You Sure to delete this?')"><i class=" fa
                                                    fa-trash"></i>Delete</button>

//First update your form and give the button a type of submit

1 like
warpig's avatar
Level 12

By using Route::delete that would mean Id have to create a delete function?

MichalOravec's avatar

Route has to be delete

Route::delete('/posts/destroy/{slug}', 'PostsController@destroy')->middleware('auth');

And code inside controller should be like this

public function destroy($slug)
{
    $post = Post::where('slug', $slug)->firstOrFail();
        
    $post->delete();

    return redirect('posts/');
}
1 like
warpig's avatar
Level 12

Still see the error, though ive changed my button to be of the type "submit", but I wonder if Im still going to be needing a delete method as well as the destroy one, so perhaps something like this:

    public function delete($slug){
        $post = Articles::find($slug)
        return view('posts/');

    }

Which is something @geordiejackson mentioned.. i.e. use the Route::delete method to initiate a delete request.

warpig's avatar
Level 12

Thank you. Sadly it isn't working, but I thank you for taking the time to reply.

MichalOravec's avatar
Level 75

Why do you use slug?

With id it will be

Route::delete('/posts/destroy/{id}', 'PostsController@destroy')->middleware('auth');
public function destroy($id)
{
    $post = Post::findOrFail($id);
        
    $post->delete();

    return redirect('posts/');
}
<form method="POST" action="/posts/destroy/{{ $post->id}}">
    @csrf
    
    @method('DELETE')
    
    <button type="submit"> 
        <span>
            <i class="fas fa-skull-crossbones"></i> Delete 
        </span>
    </button>
</form>

Or you can use route model binding

https://laravel.com/docs/8.x/routing#route-model-binding

And better to use named routes

https://laravel.com/docs/8.x/routing#named-routes

tinkerbell's avatar

Use

php artisan route:list

and see if the route created or not!

1 like

Please or to participate in this conversation.