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

Search for a command to run...

No comments yet. Be the first to comment.
Often when talking to people about preferred travel destinations or travel plans, I am surprised how different what I like to do is from what most people like do as travelers. For example, I genuinely
I have been setting up Google Stitch MCP to see if I can keep a single source of truth for design documentation inside my project, and then use Stitch to generate ideas and UI prototypes from that dir
The following is my attempt to decipher what Leonard Susskind communicates in Lecture 3: Dynamics of Theoretical Minimum: What You Need to Know to Start Doing Physics, when he formulates “Aristotle’s Law of Motion”, and shows that this law doesn’t ho...
When I have a really good prompt in ChatGPT that did what I wanted it to do. In particular, when it was something data-wrangling related. For example, when I supplied the prompt with JSON or HTML, or some leading spaces, and new lines. By default, af...
For some reason, since Laravel 12, official Laravel docs no longer provide guidance on how to set up Laravel project locally with Laravel Sail, without having PHP available on your machine - i.e. goin
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:
use Illuminate\Support\Facades\Validator;
Validator::make([], [])->after(function ($validator) {
if ($this->somethingIsInvalid()) {
$validator->errors()->add('some_error', 'Something is invalid.');
}
})->validate();
with this:
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), but in situations where you need to use it, your code becomes slightly clearer
I recently wanted to throw Illuminate\Validation\ValidationException when Stripe transfer to a connected account 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 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:
<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, 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:
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 :)