Shivamyadav's avatar

don't want to update a older category image ?

my edit form data from the browser.

<form action="http://restaurent-app.test/admin/categories/18" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="_token" value="WumE6IC65giVihLTOl4lIlQzPa83VmHQIfd9GiIt" autocomplete="off"> <input type="hidden" name="_method" value="PUT">
    <div class="space-y-3">
        <div class="space-y-2">
            <label class="font-mono">Category Name</label>
            <input class="px-3 block w-full border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none" value="Upton Mayer" name="name" type="text">


        </div>

        <div class="space-y-2">
            <label class="font-mono">Image</label>
            <input class="px-3 block w-full border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none border py-2" value="tim-mossholder-WE_Kv_ZB1l0-unsplash.jpg" name="image" type="file">


            <p class="text-red-500 text-sm">
                The image field is required.
            </p>
        </div>

        <div class="space-y-2">
            <label class="font-mono">Description</label>
            <textarea class="w-full px-1 rounded border border-gray-200" cols="5" rows="3" name="description">Fuga Voluptatem Te</textarea>
        </div>
    </div>

    <div class="py-3 flex justify-between items-center md:justify-end gap-10">
        <a class="px-3 py-2 rounded-md shadow-md  hover:text-white hover:bg-yellow-500 border border-yellow-400" href="http://restaurent-app.test/admin/categories">
            Cancel
        </a>

        <button type="submit" class="bg-blue-600 text-white px-3 py-2 rounded-md shadow-md hover:bg-blue-700">
            Update
        </button> </div>
</form>

my controller update method

public function update(CategoryRequest $request, Category $category)
    {
        $imageName = $category->image; // Default to the current image name

        // Check if a new image was uploaded
        $image = $request->file('image');
        if ($image) {
            $imageName = $image->getClientOriginalName();
            $image->storeAs('public/categories', $imageName);

            // Delete the old image if it exists
            if ($category->image) {
                unlink('public/categories/' . $category->image);
            }
        }

        // Update the category
        $category->update([
            'name' => $request->name,
            'description' => $request->description,
            'image' => $imageName,
        ]);

        session()->flash('msg', 'Category updated successfully.');
        return redirect()->route('categories.index');
    }

and I want to achieve the functionality when editing the category if user is not sending any images then what to do ? In other words he thinks older image was perfect so don't need to update that image. As I have added a required validation for the image also , due to that required validation it asking me image that it is required how to handle it?

0 likes
10 replies
gych's avatar

If the category already has an image skip the validation for the image and if it doesn't already have a category image execute the validation.

Shivamyadav's avatar

@gych here is my validation what changes needs to made

 return [
            'name' => 'required|min:3|max:80|string',
            'description' => 'required|min:3|max:300',
            'image' => 'required|image|mimes:jpg,png',
        ];

and my controller how to apply logic that if a category has already an image then skip the validation

 public function update(CategoryRequest $request, Category $category)
    {
        $imageName = $category->image; // Default to the current image name

        // Check if a new image was uploaded
        $image = $request->file('image');
        if ($image) {
            $imageName = $image->getClientOriginalName();
            $image->storeAs('public/categories', $imageName);

            // Delete the old image if it exists
            if ($category->image) {
                Storage::delete('public/categories/' . $category->image);
            }
        }

        // Update the category
        $category->update([
            'name' => $request->name,
            'description' => $request->description,
            'image' => $imageName,
        ]);

        session()->flash('msg', 'Category updated successfully.');
        return redirect()->route('categories.index');
    }
gych's avatar

@Shiv If you use the validation directly in the controller you can do this:

        $request->validate([
			// Add other validation rules
            'image' => $category->image ?: 'required|image|mimes:jpg,png',
        ]);

This will only execute the validation if $category->image is NULL

Snapey's avatar

@gych how will they ever be in a position where the image is empty?

Snapey's avatar

Why are you pasting here the rendered html and not the blade file?

Snapey's avatar

if updating the image is optional then you need to start the rule with nullable and not required.

Then you need to test if the request contains an image and if so, only then store it. Since then the $imageName is optional, dont use the update method, and use save() instead

    public function update(CategoryRequest $request, Category $category)
    {

        // Check if a new image was uploaded
       if ($request->hasFile('image')) {
            $image = $request->file('image');
            
            $imageName = $image->getClientOriginalName();
            $image->storeAs('public/categories', $imageName);

            // Delete the old image if it exists
            if ($category->image) {
                unlink('public/categories/' . $category->image);
            }
            $category->image = $imageName;
        }


        $category->name = $request->name;
        $category->description = $request->description;
        $category->save();

        session()->flash('msg', 'Category updated successfully.');
        return redirect()->route('categories.index');
    }

Please note that your image filename is not a good solution. This allows the user to accidentally overwrite a category image (with the same name) and then potentially delete the image used by two categories. There is no good reason to ever use the filename provided by the user. You should also normalise your image with something like intervention so that all images are the same size and aspect ratio.

Shivamyadav's avatar

@Snapey here is my updated controller method

 // Check if a new image was uploaded
        $image = $request->file('image');
        if ($image) {
            $imageName = $image->hashName(); // Generate a unique, random name...
            $imageExtension = $image->getClientOriginalExtension();
            $image->storeAs('public/categories', $imageName . $imageExtension);

            // Delete the old image if it exists
            if ($category->image) {
                Storage::delete('public/categories/' . $category->image);
            }
        }

        // Update the category
        $category->update([
            'name' => $request->name,
            'description' => $request->description,
            'image' => $imageName . $imageExtension ?? $category->name,
        ]);

        session()->flash('msg', 'Category updated successfully.');
        return redirect()->route('categories.index');
    }

but what about the required image should i remove it from the request validation class?

CrypticCoder's avatar

try use this code

//in validation rule 
         $validator = Validator::make($request->all(),[
            'image' => 'sometimes|nullable|mimes:jpg,png,jpeg,webp,pdf|max:1024' ,   //set to sometimes nullable if you dont want to  make image required while updating image      
        ],[
            'image.mimes' => 'upload payment receipt in jpg , png, jpeg or format.',
            'image.max' => 'Image size must be under 1 MB',           
        ]);

//update form code 
$data = $request->all();
if ($request->hasFile('image')) {
$image = $request->image;
$imageName = uniqid(). ".". $image->extension();
$data['image'] = $imageName;
$image->move(public_path('your-image-saving-path'), $imageName);
//delete old image 
if (!empty($category->image)) {
                unlink('your-image-saving-path' . $category->image);
            }

}
$category->update($data); //to use this function you need to mass assign the column name in your model
session()->flash('msg', 'Category updated successfully.');
return redirect()->route('categories.index');
1 like

Please or to participate in this conversation.