[SOLVED] How to check all if using php?

Issue

This Content is from Stack Overflow. Question asked by mex202

. I have a Validation class and a failure method which takes 2 strings as parameters. My problem is that I have to go through all the ifs and finally put as parameters for this function, which fields have passed the validation and display the appropriate message. With the current code, unfortunately, it only displays a message for the last field that did not pass validation, and it should for all that did not pass. I will be grateful for your help.

class Validation
{
    private function __construct(private array $fieldsAndMessages)
    {
    }
 
    public static function failure(string $fieldName, string $message): Validation
    {
        return new self([$fieldName => $message]);
    }
}
    $field = '';
    $message = '';
     
           if ($request->settingsSubmit()) {
               if ($request->wantsSubmitPhoto()) {
                   $extensionPhoto = new PhotoExtension($request->photo());
                   if (!in_array($extensionPhoto->getExtension(), ['jpg', 'png', 'jpeg'])) {
                       $field = 'photo';
                       $message = 'Invalid photo';
                   }
               }
     
               if ($request->wantsSubmitAvatar()) {
                   $extensionAvatar = new AvatarExtension($request->avatar());
                   if (!in_array($extensionAvatar->getExtension(), ['jpg', 'png', 'jpeg'])) {
                       $field .= 'avatar';
                       $message .= 'Invalid avatar';
                   }
     
    return new SettingsView($userId, Validation::failure($field, $message));



Solution

UPDATE

as the OP has mentioned that he cannot modify the failure method (which should’ve done in the question itself), I will provide a potentially possible workaround.

The idea is to keep the Validation class as is without modifying it and instead you may have an array that will hold instances of the Validation class where each error found will create a new instance of Validation class.

/** this variable will hold all the potential errors where each error is an instance of Validation class */
$errors = [];
if ($request->settingsSubmit()) {
    if ($request->wantsSubmitPhoto()) {
        $extensionPhoto = new PhotoExtension($request->photo());
        if (!in_array($extensionPhoto->getExtension(), ['jpg', 'png', 'jpeg']))
            $errors[] = Validation::failure('photo', 'Invalid photo');
    }

    if ($request->wantsSubmitAvatar()) {
        $extensionAvatar = new AvatarExtension($request->avatar());
        if (!in_array($extensionAvatar->getExtension(), ['jpg', 'png', 'jpeg']))
            $errors[] = Validation::failure('avatar', 'Invalid avatar');
    }
}

/** 
* pass the array ($errors) containing the errors to the SettingsView class.
* the "SettingsView" class should expect an array of `Validation` class as the second parameter.
*/
return new SettingsView($userId, $errors);

Original Answer

With your current implementation, you keep on overriding the $field and $message variables and you’ll always have 0 or 1 error.

To allow having more than one error, you may tweak your Validation class’ failure method and have it accept an array of error messages instead of a expecting a field and a message which will allow you to display all the found errors when your validation process fails.

The errors array that the failure method expects should have the following structure: the keys are the field name and the values are the actual messages (not required, I based that upon the usage of field names in your code and because you try to store the names of the fields having errors).

Here’s an example of an error messages array that you may now pass to your method:

$errors = [
    /** the keys are the fields | the values are the messages  */
    'photo' => 'Invalid photo',
    'avatar' => 'Invalid avatar',
];

Your failure method could be refactored as the following to accept an array of error messages:

/** accepts an array of error messages where the keys act as the field names and the values as the actual error messages for the fields */
public static function failure(array $errors): self
{
    /** pass the received array to the constructor */
    return new self($errors);
}

An example of usage that is based on your validation flow could be as follows:

/** this variable will hold all the potential errors */
$errors = [];
if ($request->settingsSubmit()) {
    if ($request->wantsSubmitPhoto()) {
        $extensionPhoto = new PhotoExtension($request->photo());
        if (!in_array($extensionPhoto->getExtension(), ['jpg', 'png', 'jpeg']))
            $errors['photo'] = 'Invalid photo';
    }

    if ($request->wantsSubmitAvatar()) {
        $extensionAvatar = new AvatarExtension($request->avatar());
        if (!in_array($extensionAvatar->getExtension(), ['jpg', 'png', 'jpeg']))
            $errors['avatar'] = 'Invalid avatar';
    }
}

/** pass the array ($errors) containing the errors to the failure method */
return new SettingsView($userId, Validation::failure($errors));

Now your Validation class should have the errors in an array which you may later loop through those errors and display them for the user.

Disclaimer: The above code examples are not expected to work as is as they only meant to showcase the answer’s idea and to demonstrate it. I recommend you take the idea from them and the above logic/explanations above and build upon. Also, that’s one way of doing the things and it’s definitely not the only possible way to get you on track.


This Question was asked in StackOverflow by mex202 and Answered by ths It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?