DEV Community

Ghulam Mujtaba
Ghulam Mujtaba

Posted on

Automatically Redirect Back Upon Failed Validation

Form validation refactoring

Once again back into same controller that handles logging in user. In this I will point your attention to all about form validation. Let in future when you want to create multiple forms in your application then you may to intensitiate the form, validation, event and duplicate part of code to give back the last submitted form and redirects it to desired page in every single controller if you work using this file.

 

 $email = $_POST['email'];
$password = $_POST['password'];

$form = new LoginForm();

if ($form->validate($email, $password)) {
    if ((new Authenticator)->attempt($email, $password)) {
        redirect('/');
    }

    $form->error('email', 'No matching account found for that email address and password.');
}

Session::flash('errors', $form->errors());

return redirect('/login');
Enter fullscreen mode Exit fullscreen mode

According to this firstly we are creating a new form then validating it. To refactor this we have to remove first grab out parameters of first if conditional and remove the conditional. then we have to inline new form and validate statement as:
LoginForm::validate($email, $password);

LoginForm class

Let's see if it can work , go to to LoginForm change the public function validate() to public static function validate () the all data inside it becomes static constructor then create a _construct method that can accept email and password in single form only $attribute, also validate method can accept an array of attributes then to move up to static construct method .

protected $errors = [];

    public function __construct($attributes)
    {
        if (!Validator::email($attributes['email'])) {
            $this->errors['email'] = 'Please provide a valid email address.';
        }

        if (!Validator::string($attributes['password'],100 )) {
            $this->errors['password'] = 'Please provide a valid password.';
        }

    }

    public static function validate($attributes)
    {
        $instance = new static($attributes);

        if($instance->failed()){
            throw new ValidationException();
        }
        
       return $instance;

Enter fullscreen mode Exit fullscreen mode

Calling _construct method

So that when I call a static constructor firstly have to intensiate a class with dedicated instance, count errors If any validation fails throw new exception in LoginForm.php as 'throw new /Exception but we are using ValidationException class so:

public static function validate($attributes)
    {
        $instance = new static($attributes);

        if($instance->failed()){
            throw new ValidationException();
        }
        
       return $instance;
Enter fullscreen mode Exit fullscreen mode

Try-catch block

When we run the it shows errors that $form is not accessible to fix this issue we have to wrap it in try and catch method as :

try {

    $form = LoginForm::validate($attributes = [
'email' => $_POST['email'],
'password' => $_POST['password']
]);
} catch (ValidationException $exception) {
    Session::flash('errors', $form->errors());
    Session::flash('old', [
        'email' => $attributes['email']
    ]);
        return redirect('/login');
}

Enter fullscreen mode Exit fullscreen mode

Try checks either the to create a new form that accepts email and password, while catch method catches the data to check validation.

ValidationException class

At this stage Validation Exception file is empty so the errors are not accessible and the last submitted form is not showing to user. To solve this issue using ValidationException class directory in this we have to intialize the errors and password as public read-only array as there value is one time declare by user and is not updated .

namespace Core;

class ValidationException extends \Exception
{
    public readonly array $errors;
    public readonly array $old;   
    public static function throw($errors, $old){
        $instance = new static;
        $instance-> errors = $errors;
        $instance->old=$old; 
        throw $instance;
        ;
    }
}

Enter fullscreen mode Exit fullscreen mode

Now you can check the project is working well and everything showing on output screen.

I hope that you have been clearly
Understood it.

Top comments (0)