I've made a (service) class to handle all form validation of my application. It contains a set of frequently used validation callables extracted into private methods that I use to build each is[FormName]Valid();
method. It would probably end up containing validation logic for about 5 or 6 forms of which it contains 2 already. So the class could become relatively big; roughly about 230 lines.
It works completely fine and was the best solution I could think of. But since this would pretty much be considered a god object, at some point I would want to adapt to a better pattern. I've got some clues that my class might be somewhat extraordinary, because I haven't seen anyone else do it like this before.
Are there any better / more efficient solutions?
namespace Model\Application;
use Library\Validator;
use Model\Infrastructure\Mapper\UserMapper;
class FormValidationService
{
private $validator;
private $userMapper;
private $errors;
public function __construct(Validator $validator, UserMapper $userMapper)
{
$this->validator = $validator;
$this->userMapper = $userMapper;
}
public function isLoginValid($email, $password)
{
$this->validator->reset();
$this->validator->isValid('email', [
$this->notEmpty($email),
$this->email($email),
]);
$this->validator->isValid('password', [
$this->notEmpty($password),
$this->minChars($password, 6)
]);
return !$this->errors['Login'] = $this->validator->findErrors();
}
public function isSignUpValid($firstName, $lastName, $email, $confirmationEmail, $password, $terms)
{
$this->validator->reset();
$this->validator->isValid('firstName', [
$this->notEmpty($firstName),
$this->maxChars($firstName, 35)
]);
$this->validator->isValid('lastName', [
$this->notEmpty($lastName),
$this->maxChars($lastName, 35)
]);
$this->validator->isValid('email', [
$this->notEmpty($email),
$this->email($email),
$this->uniqueUserEmail($email)
]);
$this->validator->isValid('confirmationEmail', [
$this->notEmpty($confirmationEmail),
$this->email($confirmationEmail),
$this->match($confirmationEmail, $email)
]);
$this->validator->isValid('password', [
$this->notEmpty($password),
$this->minChars($password, 6)
]);
$this->validator->isValid('terms', [
$this->notEmpty($terms)
]);
return !$this->errors['SignUp'] = $this->validator->findErrors();
}
public function findErrorsOf($formName)
{
return isset($this->errors[$formName]) ? $this->errors[$formName] : [];
}
private function notEmpty($input)
{
return (function () use ($input) {
return !empty($input) ?: 'NotEmpty';
});
}
private function minChars($input, $min)
{
return (function () use ($input, $min) {
return mb_strlen($input, mb_detect_encoding($input)) >= $min ?: 'MinChars';
});
}
private function maxChars($input, $max)
{
return (function () use ($input, $max) {
return mb_strlen($input, mb_detect_encoding($input)) <= $max ?: 'MaxChars';
});
}
private function email($input)
{
return (function () use ($input) {
$sanitized = filter_var($input, FILTER_SANITIZE_EMAIL);
$isValid = filter_var($sanitized, FILTER_VALIDATE_EMAIL);
return $input === $sanitized && $isValid ?: 'Email';
});
}
private function match($input1, $input2)
{
return (function () use ($input1, $input2) {
return $input1 === $input2 ?: 'Match';
});
}
private function uniqueUserEmail($input)
{
return (function () use ($input) {
return !$this->userMapper->findByEmail($input) ? true : 'Unique';
});
}
}