# How to throw ValidationException in Laravel without Request validation helpers or manually creating a Validator?

## How to use `ValidationException::withMessages()` method?

Instead of manually creating a Validator, then adding some rules into it, and executing `validate()` method on the Validator, you can directly throw `ValidationException` with error messages in it.

Compare this:

```php
use Illuminate\Support\Facades\Validator;

Validator::make([], [])->after(function ($validator) {
    if ($this->somethingIsInvalid()) {
        $validator->errors()->add('some_error', 'Something is invalid.');
    }
})->validate();
```

with this:

```php
use Illuminate\Validation\ValidationException;

if ($this->somethingIsInvalid()) {
    throw ValidationException::withMessages([
        'some_error' => 'Something is invalid.'),
    ]);
}
```

The end result is the same, and if you use `ValidationException::withMessages()`, Laravel internally still calls `Validator::make([], [])` ([source](https://github.com/laravel/framework/blob/v10.7.1/src/Illuminate/Validation/ValidationException.php#L69)), but in situations where you need to use it, your code becomes slightly clearer

## When you may need to manually throw ValidationException?

I recently wanted to throw `Illuminate\Validation\ValidationException` when Stripe transfer to a [connected account](https://stripe.com/docs/connect/accounts) failed due to some error on Stripe's end. For example, if the connected account was not fully onboarded, Stripe wouldn't let us execute the transfer. We find out about the failure when [Stripe PHP](https://github.com/stripe/stripe-php) throws `Stripe\Exception\ApiErrorException`.

Executing Stripe transfers is something that one of the admin users does in our app. I simply wanted to use the existing front-end components displaying validation messages to communicate to the admin that something went wrong and pass the message we received from Stripe. In other words, I wanted these errors to be shown within blade templates like:

```php-template
<ul>
    @foreach ($errors->all() as $error)
        <li>{!! $error !!}</li>
    @endforeach
</ul>
```

I could have adjusted the front-end templates, and [flash custom messages into session](https://laravel.com/docs/10.x/session#flash-data), but somehow Stripe errors fall into my mental model of validation errors, so it feels better to wrap them into a `ValidationException`. I think of them as Stripe telling me "you didn't provide us a valid connected account id that is eligible for transfers".

So here's how I solved it:

```php
try {
    $stripeTransfer = $stripeGateway->transfer($amount, $currency, $connectedAccountId, $internalTransferId, $description);
} catch (ApiErrorException $e) {
    // manually add errors to session:
    // https://stackoverflow.com/a/48619721/4171578
    throw ValidationException::withMessages([
        'gateway' => $e->getMessage(),
    ]);
}

// ...
// do something else with the $stripeTransfer, if we successfully executed it
```

This may not be a pattern you use very often in your app, but it's good to know that something like this exists :)
