Build a CRUD App — Step by StepCore· 35 min read

CRUD Step 5: Delete + Success Messages

Safely delete a record with a small form, and show friendly “done!” messages after every action.

What you will learn

  • Delete a record the safe way (a form, not a link)
  • Write the destroy() method
  • Show one-time flash messages to the user

Delete = a tiny form + destroy()

Deleting must use a POST/DELETE form, never a plain link. (A link is a GET request, and search engines or browser prefetchers can follow links — which could quietly delete all your data!) So the delete button is a tiny form.

The delete button (add it to each row in index.blade.php)

A delete form — put it in the Actions column of the list
<form method="POST" action="{{ route('products.destroy', $product) }}"
      onsubmit="return confirm('Delete this product?')" style="display:inline">
  @csrf
  @method('DELETE')
  <button type="submit">Delete</button>
</form>

The parts: it POSTs to products.destroy with $product; @csrf adds the security token; @method('DELETE') spoofs a DELETE request so it reaches destroy(); and onsubmit="return confirm(...)" pops up a “Are you sure?” box so nobody deletes by accident.

The destroy() method

destroy() in ProductController
public function destroy(Product $product)
{
    $product->delete();

    return redirect()->route('products.index')
                     ->with('success', 'Product deleted!');
}

Route model binding finds the product, $product->delete() removes its row, and we redirect to the list with a success message.

Watch out: Never delete with a normal link like <a href="/products/5/delete">. Crawlers and prefetchers follow links automatically and could wipe your records. Deletes must always be a form with @method('DELETE').

Show the success messages

Every action above redirected with ->with('success', '...'). That stores a flash message — a value that survives exactly one redirect and then disappears. Show it at the top of the list page so the user gets feedback:

Put this near the top of index.blade.php (or your layout)
@if (session('success'))
  <div style="background:#dcfce7; padding:10px; border-radius:8px">
    {{ session('success') }}
  </div>
@endif

session('success') reads the flash message set by ->with('success', ...). It shows once, then is gone on the next page load — perfect for “Product added!”, “Product updated!”, “Product deleted!”.

Note: Output: Click “Delete” → a confirm box appears → confirm → the row vanishes and a green “Product deleted!” banner shows at the top of the list. 🎉 Your CRUD is complete: you can now list, add, edit and delete products — with validation and friendly messages. That is a real, working feature you built and understand.

Q. Why must deleting use a form with @method('DELETE') instead of a link?

Answer: A GET link can be auto-followed by bots, prefetchers or accidental clicks and delete data. A POST/DELETE form (with confirm) is the safe way.

✍️ Practice

  1. Add the delete form to your list and the destroy() method, and delete a product end to end.
  2. Add the flash-message block and watch the green banner appear after add/edit/delete.

🏠 Homework

  1. List the full journey of one product through your app: created → listed → edited → deleted, naming the route and controller method used at each step.
Want to learn this with a mentor?

CodingClave runs guided, project-based training (28-day, 45-day & 6-month batches).

Explore Training →