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 key
s are the field name and the value
s 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.