Automatically Redirect Back Upon Failed Validation
Tags: webdev, beginners, programming, tutorial
Published: 2024-07-12 19:18:59

## 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.
 

```php
 $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');
```

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 .

```php
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;

```

## 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:

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

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

## 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 :

```php
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');
}

```
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 .

```php
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;
        ;
    }
}

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

I hope that you have been clearly 
Understood it.