skip to Main Content

Lets say I have an image field image with the following validation rules: required|image|mimes:jpg,jpeg|max:2048 and after successful validation and saving of the model the image gets saved in a directory.

My current approach is that after that the model’s image field value will be the path to the image, like storage/images/file.jpg. This has the following drawback:

When editing the model again and not changing the image (i. e. uploading another image) the request does not contain the image field so its requirement rule will fail.

I could only validate its rules when there is an upload present in the request but it feels like I am missing something. Is it generally bad practice to save the path in the file/ upload field? Is there a streamlined way of doing this?

Another approach might be treating each uploaded file as a model and use relationships, but I feel like this is overkill.

Edit: I feel like there could be a Rule "Validate as image when a file is being uploaded" but I guess I have to do that with custom logic.

2

Answers


  1. I think you can create a custom validation rule that validates your image field only when there is a file uploaded, let me show you how, first of all create a custom validation rule class(e.g., ImageUploadRule) like this :

    php artisan make:rule ImageUploadRule
    

    and then open your generated ImageUploadRule class and update the passes method

    public function passes($attribute, $value){
           //checking if a file was uploaded
           if (request()->hasFile('image')) {
               //validation of the image field
               return request()->file('image')->isValid();
           }
           //no file uploaded, so it's considered valid
           return true;
    }
    

    and finally in your controller’s validation logic, you can use the new ImageUploadRule in the validation rules for the image field and if no file is uploaded, your validation will pass, allowing you to update the model without changing the image, like this:

    $validatedData = $request->validate([
           'image' => ['nullable', 'image', 'mimes:jpg,jpeg', 'max:2048', new ImageUploadRule],
           //put other of your validation rules in here!
       ]);
    
    Login or Signup to reply.
  2. Actually there already is a validation Rule to do exactly that. sometimes

    Your Validation rule would look like this:

    'image' => 'sometimes|required|image|mimes:jpg,jpeg|max:2048'
    

    Now the rules will be applied only if the data is present in the request.

    https://laravel.com/docs/10.x/validation#validating-when-present

    If you want to only make it required if the model has no path use the Rule Facade

    Then you could use the Rule Facade to make a required_if Like so

    Rule::requiredIf(fn() => !$myModel?->path_to_image)
    

    https://laravel.com/docs/10.x/validation#rule-required-if

    To your first question. Its completely fine to save the filepath directly in the database. That way you’re also able to use the asset() helper without any additional info as the path.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search