Skip to content

Instantly share code, notes, and snippets.

@a-h-abid
Created October 13, 2023 18:44
Show Gist options
  • Save a-h-abid/aea68defb6145846e9449a1ce3421e20 to your computer and use it in GitHub Desktop.
Save a-h-abid/aea68defb6145846e9449a1ce3421e20 to your computer and use it in GitHub Desktop.
Laravel 10+ Validator Response with Rule Names
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Validation\ValidationException;
class Handler extends ExceptionHandler
{
// ...
/**
* @inheritDoc
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json([
'message' => 'Validation Errors',
'errors' => $exception->errors(),
], $exception->status);
}
}
<?php
namespace App\Providers;
use App\Exceptions\LaravalidaterrorsException;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Validator::resolver(function ($translator, $data, $rules, $messages, $customAttributes) {
$validator = new \Illuminate\Validation\Validator($translator, $data, $rules, $messages, $customAttributes);
$validator->setException(LaravalidaterrorsException::class);
return $validator;
});
}
}
<?php
namespace App\Exceptions;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Str;
use ReflectionClass;
class LaravalidaterrorsException extends ValidationException
{
/**
* Clear params for rules
*/
protected array $clearRuleParams = ['unique'];
/**
* Set rules to clear params for
*/
public function setClearRuleParams(array $rules = []): static
{
$this->clearRuleParams = $rules;
return $this;
}
/**
* @inheritDoc
*/
public function errors(): array
{
$result = [];
$errors = $this->validator->errors()->messages();
foreach ($this->validator->failed() as $field => $rules) {
if (!isset($errors[$field])) {
continue;
}
$result[$field] = [];
$i = 0;
foreach ($rules as $rule => $params) {
$ruleErrors = $this->extractRuleErrors($rule, $params);
$ruleErrors['message'] = $errors[$field][$i] ?? '';
$result[$field][] = $ruleErrors;
$i++;
}
}
return $result;
}
/**
* Extract rule name & parameters
*/
protected function extractRuleErrors(string $rule, array $params): array
{
$ruleName = mb_strtolower($rule);
$ruleParams = $params;
if (class_exists($rule)) {
[$ruleName, $ruleParams] = $this->extractRuleClassDetails($rule);
}
return [
'rule' => $ruleName,
'options' => $this->filerRuleParams($ruleName, $ruleParams),
];
}
/**
* Extract Custom Rule Class Details
*
* @return [string, array]
*/
protected function extractRuleClassDetails(string $rule): array
{
$refection = new ReflectionClass($rule);
$props = $refection->getConstants() ?? [];
$ruleName = '';
if (array_key_exists('RULE_NAME', $props)) {
$ruleName = mb_strtolower($props['RULE_NAME']);
} else {
$ruleName = Str::of($refection->getShortName())->snake('-')->lower();
}
$ruleParams = [];
if (array_key_exists('RULE_PARAMS', $props)) {
$ruleParams = $props['RULE_PARAMS'];
}
return [$ruleName, $ruleParams];
}
/**
* Filter Rule Params
*/
protected function filerRuleParams(string $ruleName, array $params): array
{
if (in_array($ruleName, $this->clearRuleParams)) {
return [];
}
return $params;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment