Laravel 11 E-Commerce - Admin Edit Product

Welcome back to the Laravel E-Commerce Project Tutorial! In this video, we are going to learn about editing a product.

Creating the Edit Function

So, let's see how we can edit the product. So, first of all, go to the AdminController and create a function:


public function edit_product($id)
{
$product = Product::find($id);
$categories = Category::Select('id','name')->orderBy('name')->get();
$brands = Brand::Select('id','name')->orderBy('name')->get();
return view('admin.product-edit',compact('product','categories','brands'));
}

Creating the Route

Now, create the route for this. So, go to the web.php file and create a new route:


Route::get('/admin/product/{id}/edit',[AdminController::class,'edit_product'])->name('admin.product.edit');

Creating the View

Now, let's create this view. Go to the resources directory and create a new file. Now, go to the product-add.blade.php, let's copy all the text and paste inside the product-edit.blade.php file, and make changes as follows:


@extends('layouts.admin')

@section('content')
<!-- main-content-wrap -->
<div class="main-content-inner">
<!-- main-content-wrap -->
<div class="main-content-wrap">
<div class="flex items-center flex-wrap justify-between gap20 mb-27">
<h3>Add Product</h3>
<ul class="breadcrumbs flex items-center flex-wrap justify-start gap10">
<li>
<a href="index.html"><div class="text-tiny">Dashboard</div></a>
</li>
<li>
<i class="icon-chevron-right"></i>
</li>
<li>
<a href="all-product.html"><div class="text-tiny">Products</div></a>
</li>
<li>
<i class="icon-chevron-right"></i>
</li>
<li>
<div class="text-tiny">Add product</div>
</li>
</ul>
</div>
<!-- form-add-product -->
<form class="tf-section-2 form-add-product" method="POST" enctype="multipart/form-data" action="{{route('admin.product.update')}}" >
<input type="hidden" name="id" value="{{$product->id}}" />
@csrf
@method("PUT")
<div class="wg-box">
<fieldset class="name">
<div class="body-title mb-10">Product name <span class="tf-color-1">*</span></div>
<input class="mb-10" type="text" placeholder="Enter product name" name="name" tabindex="0" value="{{$product->name}}" aria-required="true" required="">
<div class="text-tiny">Do not exceed 100 characters when entering the product name.</div>
</fieldset>

<fieldset class="name">
<div class="body-title mb-10">Slug <span class="tf-color-1">*</span></div>
<input class="mb-10" type="text" placeholder="Enter product slug" name="slug" tabindex="0" value="{{$product->slug}}" aria-required="true" required="">
<div class="text-tiny">Do not exceed 100 characters when entering the product name.</div>
</fieldset>

<div class="gap22 cols">
<fieldset class="category">
<div class="body-title mb-10">Category <span class="tf-color-1">*</span></div>
<div class="select">
<select class="" name="category_id">
<option>Choose category</option>
@foreach ($categories as $category)
<option value="{{$category->id}}" {{$product->category_id == $category->id ? "selected":""}}>{{$category->name}}</option>
@endforeach
</select>
</div>
</fieldset>
<fieldset class="brand">
<div class="body-title mb-10">Brand <span class="tf-color-1">*</span></div>
<div class="select">
<select class="" name="brand_id">
<option>Choose Brand</option>
@foreach ($brands as $brand)
<option value="{{$brand->id}}" {{$product->brand_id == $brand->id ? "selected":""}}>{{$brand->name}}</option>
@endforeach
</select>
</div>
</fieldset>
</div>

<fieldset class="shortdescription">
<div class="body-title mb-10">Short Description <span class="tf-color-1">*</span></div>
<textarea class="mb-10 ht-150" name="short_description" placeholder="Short Description" tabindex="0" aria-required="true" required="">{{$product->short_description}}</textarea>
<div class="text-tiny">Do not exceed 100 characters when entering the product name.</div>
</fieldset>

<fieldset class="description">
<div class="body-title mb-10">Description <span class="tf-color-1">*</span></div>
<textarea class="mb-10" name="description" placeholder="Description" tabindex="0" aria-required="true" required="">{{$product->description}}</textarea>
<div class="text-tiny">Do not exceed 100 characters when entering the product name.</div>
</fieldset>
</div>
<div class="wg-box">
<fieldset>
<div class="body-title">Upload images <span class="tf-color-1">*</span></div>
<div class="upload-image flex-grow">
@if($product->image)
<div class="item" id="imgpreview">
<img src="{{asset('uploads/products')}}/{{$product->image}}" class="effect8" alt="">
</div>
@endif
<div id="upload-file" class="item up-load">
<label class="uploadfile" for="myFile">
<span class="icon">
<i class="icon-upload-cloud"></i>
</span>
<span class="body-text">Drop your images here or select <span class="tf-color">click to browse</span></span>
<input type="file" id="myFile" name="image" accept="image/*">
</label>
</div>
</div>
</fieldset>

<fieldset>
<div class="body-title mb-10">Upload Gallery Images</div>
<div class="upload-image mb-16">
@if($product->images)
@foreach(explode(",",$product->images) as $img)
<div class="item gitems">
<img src="{{asset('uploads/products')}}/{{trim($img)}}" class="effect8" alt="">
</div>
@endforeach
@endif

<div id ="galUpload" class="item up-load">
<label class="uploadfile" for="gFile">
<span class="icon">
<i class="icon-upload-cloud"></i>
</span>
<span class="text-tiny">Drop your images here or select <span class="tf-color">click to browse</span></span>
<input type="file" id="gFile" name="images[]" accept="image/*" multiple>
</label>
</div>
</div>
</fieldset>

<div class="cols gap22">
<fieldset class="name">
<div class="body-title mb-10">Regular Price <span class="tf-color-1">*</span></div>
<input class="mb-10" type="text" placeholder="Enter regular price" name="regular_price" tabindex="0" value="{{$product->regular_price}}" aria-required="true" required="">
</fieldset>
<fieldset class="name">
<div class="body-title mb-10">Sale Price <span class="tf-color-1">*</span></div>
<input class="mb-10" type="text" placeholder="Enter sale price" name="sale_price" tabindex="0" value="{{$product->sale_price}}" aria-required="true" required="">
</fieldset>
</div>


<div class="cols gap22">
<fieldset class="name">
<div class="body-title mb-10">SKU <span class="tf-color-1">*</span></div>
<input class="mb-10" type="text" placeholder="Enter SKU" name="SKU" tabindex="0" value="{{$product->SKU}}" aria-required="true" required="">
</fieldset>
<fieldset class="name">
<div class="body-title mb-10">Quantity <span class="tf-color-1">*</span></div>
<input class="mb-10" type="text" placeholder="Enter quantity" name="quantity" tabindex="0" value="{{$product->quantity}}" aria-required="true" required="">
</fieldset>
</div>

<div class="cols gap22">
<fieldset class="name">
<div class="body-title mb-10">Stock</div>
<div class="select mb-10">
<select class="" name="stock_status">
<option value="instock" {{$product->stock_status == "instock" ? "Selected":"" }}>InStock</option>
<option value="outofstock" {{$product->stock_status == "outofstock" ? "Selected":"" }}>Out of Stock</option>
</select>
</div>
</fieldset>
<fieldset class="name">
<div class="body-title mb-10">Featured</div>
<div class="select mb-10">
<select class="" name="featured">
<option value="0" {{$product->featured == "0" ? "Selected":"" }}>No</option>
<option value="1" {{$product->featured == "1" ? "Selected":"" }}>Yes</option>
</select>
</div>
</fieldset>
</div>
<div class="cols gap10">
<button class="tf-button w-full" type="submit">Save product</button>
</div>
</div>
</form>
<!-- /form-add-product -->
</div>
<!-- /main-content-wrap -->
</div>
<!-- /main-content-wrap -->
@endsection

Adding JavaScript Code

After this, let's add the @push directive, and inside this, let's add the JavaScript code for previewing the product images and also for generating a slug:


@push("scripts")
<script>
$(function(){
$("#myFile").on("change",function(e){
const photoInp = $("#myFile");
const [file] = this.files;
if (file) {
$("#imgpreview img").attr('src',URL.createObjectURL(file));
$("#imgpreview").show();
}
});


$("#gFile").on("change",function(e){
$(".gitems").remove();
const gFile = $("gFile");
const gphotos = this.files;
$.each(gphotos,function(key,val){
$("#galUpload").prepend(`<div class="item gitems"><img src="${URL.createObjectURL(val)}" alt=""></div>`);
});
});


$("input[name='name']").on("change",function(){
$("input[name='slug']").val(StringToSlug($(this).val()));
});

});
function StringToSlug(Text) {
return Text.toLowerCase()
.replace(/[^\w ]+/g, "")
.replace(/ +/g, "-");
}
</script>
@endpush

Updating the Product

Now, go to the AdminController and let's create a new function for updating the product:


public function update_product(Request $request)
{
$request->validate([
'name'=>'required',
'slug'=>'required|unique:products,slug,'.$request->id,
'category_id'=>'required',
'brand_id'=>'required',
'short_description'=>'required',
'description'=>'required',
'regular_price'=>'required',
'sale_price'=>'required',
'SKU'=>'required',
'stock_status'=>'required',
'featured'=>'required',
'quantity'=>'required',
'image'=>'required|mimes:png,jpg,jpeg|max:2048'
]);

$product = Product::find($request->id);
$product->name = $request->name;
$product->slug = Str::slug($request->name);
$product->short_description = $request->short_description;
$product->description = $request->description;
$product->regular_price = $request->regular_price;
$product->sale_price = $request->sale_price;
$product->SKU = $request->SKU;
$product->stock_status = $request->stock_status;
$product->featured = $request->featured;
$product->quantity = $request->quantity;
$current_timestamp = Carbon::now()->timestamp;

if($request->hasFile('image'))
{
$product->image = $request->image;
$file_extention = $request->file('image')->extension();
$file_name = $current_timestamp . '.' . $file_extention;
$path = $request->image->storeAs('products', $file_name, 'public_uploads');
$product->image = $path;
}

$gallery_arr = array();
$gallery_images = "";
$counter = 1;

if($request->hasFile('images'))
{
$allowedfileExtension=['jpg','png','jpeg'];
$files = $request->file('images');
foreach($files as $file){
$gextension = $file->getClientOriginalExtension();
$check=in_array($gextension,$allowedfileExtension);
if($check)
{
$gfilename = $current_timestamp . "-" . $counter . "." . $gextension;
$gpath = $file->storeAs('products', $gfilename, 'public_uploads');
array_push($gallery_arr,$gpath);
$counter = $counter + 1;
}
}
$gallery_images = implode(', ', $gallery_arr);
}
$product->images = $gallery_images;

$product->save();
return redirect()->route('admin.products')->with('status','Record has been updated successfully !');
}

Creating the Route for Updating

Now, create the route for this. So, go to the web.php file and create a new route:


Route::put('/admin/product/update',[AdminController::class,'update_product'])->name('admin.product.update');

Adding the Edit Link

Now, go to the products.blade.php file and here, inside the foreach, add the link for editing the product:


<a href="{{route('admin.product.edit',['id'=>$product->id])}}">
<div class="item edit">
<i class="icon-edit-3"></i>
</div>
</a>

Checking the Result

Now, it's done. Let's check. So, refresh the page, and now, let's click on the edit link. And here, you can see the edit page. Now, let's change the product. Let's change the product name, description, price, also change the image and gallery image. Now, click on update. And here, you can see the product has been updated.

So, in this way, we can edit the product. That's all about editing.