CRUD Step 4: Edit a Product (Update)
Show a form pre-filled with a product’s current values, then validate and save the changes.
What you will learn
- Pre-fill an edit form with existing values
- Use @method to send a PUT request
- Reuse your validation in update()
Update = edit (pre-filled form) + update (save)
“Update” mirrors “Create”, with two differences: the form is pre-filled with the product’s current values, and it saves to the update route instead of store.
The edit() method
public function edit(Product $product)
{
return view('products.edit', compact('product'));
}Just like show, the Product $product argument makes Laravel find the right product from the URL automatically and pass it to the view.
The edit form (edit.blade.php)
It is almost the same as the create form, with three changes — read the comments:
<h1>Edit Product</h1>
<form method="POST" action="{{ route('products.update', $product) }}">
@csrf
@method('PUT') {{-- tell Laravel this is really a PUT request --}}
<label>Name</label>
<input type="text" name="name" value="{{ old('name', $product->name) }}">
@error('name') <p style="color:red">{{ $message }}</p> @enderror
<label>Price</label>
<input type="text" name="price" value="{{ old('price', $product->price) }}">
@error('price') <p style="color:red">{{ $message }}</p> @enderror
<label>Description</label>
<textarea name="description">{{ old('description', $product->description) }}</textarea>
<button type="submit">Update Product</button>
</form>The three differences from the create form: (1) the action points to products.update and includes $product so Laravel knows which product; (2) @method('PUT') is added — browsers can only really send GET and POST, so this “spoofs” a PUT request so the route reaches update(); (3) old('name', $product->name) takes two arguments — show the old typed value if validation just failed, otherwise show the product’s current value. That is what makes the form appear pre-filled.
The update() method
public function update(Request $request, Product $product)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'price' => 'required|numeric|min:0',
'description' => 'nullable|string',
]);
$product->update($validated);
return redirect()->route('products.index')
->with('success', 'Product updated!');
}update() uses the same validation as store(). The only real difference is the save step: $product->update($validated) changes the existing row (instead of creating a new one), then we redirect with a success message.
Note: Output: Click “Edit” on a product → the form opens with its current name, price and description already filled in → change the price and submit → you return to the list with “Product updated!” and the new price showing.
Tip: Notice store() and update() repeat the exact same validation rules. That duplication is annoying — the last lesson of this unit shows how a Form Request class moves the rules to one place.
Q. Why does the edit form include @method('PUT')?
✍️ Practice
- Build the edit form and
update()for your Tasks resource and edit a task end to end. - Change a price to a negative number and confirm the
min:0rule blocks it with an error.
🏠 Homework
- Explain what the second argument of
old('name', $product->name)is for.