Sending a Form to a DELETE Route in Laravel (With Example)

You might have encountered a route before that supports only requests that use the DELETE method. Let’s look into this and learn how to create forms that work with DELETE routes properly.

In Laravel defining a route that uses the DELETE method is straightforward, for example:

routes/web.php
Route::delete('/products/{products}', 'ProductController@destroy')->name('products.destroy');

A DELETE route is also added when using a resource controller like:

PHP
Route::resource('products', ProductController::class);

Natively, an HTML form sent by a browser doesn’t support using the DELETE method. Therefore, you need to add some markup to your form to ensure it works properly.

Fortunately, Laravel provides an easy solution for this!

By adding @method('DELETE') into your form, Laravel will know to handle incoming form submissions as DELETE requests. For example, your form should look somewhat like this:

HTML
<form action="{{ route('products.destroy', $product) }}" method="POST">
    @csrf
    @method('DELETE')
    <button type="submit">Delete</button>
</form>

That’s it! Under the hood, Laravel will automatically replace the @method directive with a hidden field. When receiving a form with this hidden field Laravel knows that the form data should be handled as if it were sent as a DELETE (this is called “Method spoofing”). You can see this hidden input when viewing the page source code:

HTML
<input type="hidden" name="_method" value="DELETE">

In this guide, we’ll build an example that shows a list of products and provides a form that deletes a product using a DELETE-based route.

Step 1: Create a Laravel Project

Note: in the previous post we showed how to use PUT Routes with forms, if you followed along with that guide you can reuse the code and skip steps 1,2,3 and 4

Begin by creating a new Laravel project if you haven’t done so already. Open your terminal and run:

composer create-project laravel/laravel productsapp
cd productsapp 

Step 2: Creating a Model and Migration

Generate a ‘Product’ model and a migration file to create a ‘products’ table by running the following artisan command:

php artisan make:model Product -m

This adds a model in app/Models/Product.php which we can keep unchanged for this guide.

Now we’ll edit the migration file in the folder database/migrations. In that file, we will define the database columns we will need by adding:

database/migrations/2023_11_22_204217_create_products_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('category');
            $table->decimal('price', 8, 2);
            // Add other product fields here.
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

Step 3: Create a Seeder

Now we’ll create and run a seeder to fill the products table with some test data.

Create a seeder called ProductSeeder by running:

php artisan make:seeder ProductSeeder

Now open the generated ProductSeeder.php file located in the database/seeders directory and add:

database/seeders/ProductSeeder.php
<?php

namespace Database\Seeders;

use App\Models\Product;
use Illuminate\Database\Seeder;

class ProductSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Product::create([
            'name' => 'The Lord of the Rings: The Fellowship of the Ring',
            'price' => 9.95,
            'category' => 'Fantasy Movies',
        ]);

        Product::create([
            'name' => 'Pirates of the Caribbean: The Curse of the Black Pearl',
            'price' => 9.95,
            'category' => 'Fantasy Movies',
        ]);

        Product::create([
            'name' => 'Pan\'s Labyrinth',
            'price' => 9.95,
             'category' => 'Fantasy Movies',
        ]);
    }
}

Now run the seeder using Artisan:

php artisan db:seed --class=ProductSeeder

Step 4: Create a ProductController

Create a controller for managing products:

php artisan make:controller ProductController

In the next step, we’ll add the necessary code.

Step 5: Add Code to ProductController

Next, add the following methods to the ProductController: ‘index’ to display a list of products and ‘destroy’ to delete a product:

app/Http/Controllers/ProductController.php
<?php

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index()
    {
        $products = Product::all();

        return view('products.index', compact('products'));
    }

    public function destroy(Request $request, Product $product)
    {
        $product->delete();

        return redirect()->route('products.index');
    }

    // Other methods ...
}

Step 6: Setting Up Routes

Now let’s add routes to routes/web.php to show all products (index), edit a product, and update a product.

routes/web.php
<?php

use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;

Route::get('/products', [ProductController::class, 'index'])->name('products.index');
Route::delete('/products/{product}', [ProductController::class, 'destroy'])->name('products.destroy');

// other routes ...

Step 7: Creating a View to Show Products

Now let’s create a file at views/products/index.blade.php with blade code to display a list of all products along with a link to delete a product:

Note that this is also where we’ll need to add a form with @method(‘DELETE’) to ensure it works nicely with the delete-based route we’ve defined in the previous step. We’ll make the submit button red and add the text “Delete Product” to it:

<html>
<head>
    <!-- Include Bootstrap to make it the example look better -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
            crossorigin="anonymous"></script>
</head>
<body>
<div class="container">

    <h1 class="mt-4 mb-4">All Products</h1>

    <!-- Product List -->
    <div class="row">
        @foreach($products as $product)
            <div class="col-md-4 mb-3">
                <div class="card">
                    <div class="card-body">
                        <h5 class="card-title">{{ $product->name }}</h5>
                        <p class="card-text">
                            Price: ${{ $product->price }}<br>
                            Category: {{ $product->category }}
                        </p>

                        <form action="{{ route('products.destroy', $product) }}" method="POST">
                            @method('DELETE')
                            @csrf
                            <input type="submit" class="btn btn-danger mt-3" value="Delete" />
                        </form>
                    </div>
                </div>
            </div>
        @endforeach
    </div>

    <!-- Footer -->
    <footer class="mt-5 text-center">
        <p>Created with ♥ by Laracoding</p>
    </footer>
</div>
</body>
</html>

In case you forget to add @method('DELETE') to your form you will receive this error:

“The POST method is not supported for route products/3. Supported methods: DELETE.”

To fix this simply add @method('DELETE') and try again

Step 8: Test the Application

Launch the application by running:

php artisan serve

Now navigate to http://127.0.0.1:8000/products in your browser. You should see the products listed, each with a link to delete:

Screenshot of the Products Index Page Before Deleting a Product

Now after deleting one of the products, the application will redirect us back to the index page where we can see that it is removed as expected:

Screenshot of the Products Index Page After Deleting a Product

Conclusion

Congratulations on learning how to use DELETE routes using a form in Laravel. Using simple blade directives like @method is part of what makes the developer experience with Laravel so great.

As an exercise try to add a form that updates a product using the PUT method. You may use the guide Sending a Form to a PUT Route in Laravel to see how it can be done.

Now go ahead and make something cool using these techniques. Happy coding!

References:

Johan van den Broek

Johan is the creator of laracoding.com. As a child, he began tinkering with various programming languages, many of which have been long forgotten today. Currently, he works exclusively with PHP and Laravel, and his passion for programming remains to this day.

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Posts