Skip to content

Commit d31ff59

Browse files
committed
feat: add initial validation exception renderable
1 parent fde32e1 commit d31ff59

File tree

4 files changed

+80
-4
lines changed

4 files changed

+80
-4
lines changed

config/undefined.php

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
\RedExplosion\Undefined\Renderables\AccessDeniedHttpExceptionRenderable::class,
5656
\RedExplosion\Undefined\Renderables\AuthenticationExceptionRenderable::class,
5757
\RedExplosion\Undefined\Renderables\NotFoundHttpExceptionRenderable::class,
58+
\RedExplosion\Undefined\Renderables\ValidationExceptionRenderable::class,
5859
],
5960

6061
];

src/DataObjects/ValidationData.php

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RedExplosion\Undefined\DataObjects;
6+
7+
class ValidationData
8+
{
9+
public function __construct(
10+
public readonly string $parameter,
11+
public readonly string $rule,
12+
public readonly string $message,
13+
) {
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RedExplosion\Undefined\Renderables;
6+
7+
use Illuminate\Http\Request;
8+
use Illuminate\Validation\ValidationException;
9+
use RedExplosion\Undefined\DataObjects\ValidationData;
10+
use RedExplosion\Undefined\Enums\ErrorTypeEnum;
11+
use RedExplosion\Undefined\Responses\ErrorResponse;
12+
13+
class ValidationExceptionRenderable
14+
{
15+
public function __invoke(ValidationException $exception, Request $request): ErrorResponse|null
16+
{
17+
if ($request->expectsJson()) {
18+
/** @var ValidationData $validationError */
19+
$validationError = collect($exception->errors())
20+
->flatMap(function (array $errors, string $parameter) use ($exception) {
21+
return collect($errors)
22+
->map(function ($message) use ($exception, $parameter) {
23+
/** @var string $rule */
24+
$rule = array_keys($exception->validator->failed()[$parameter])[0];
25+
26+
return new ValidationData(
27+
parameter: $parameter,
28+
rule: mb_strtolower($rule),
29+
message: $message,
30+
);
31+
});
32+
})
33+
->first();
34+
35+
return new ErrorResponse(
36+
errorType: ErrorTypeEnum::InvalidRequestError,
37+
message: $validationError->message,
38+
code: "parameter_{$validationError->rule}",
39+
param: $validationError->parameter,
40+
status: 422,
41+
);
42+
}
43+
44+
return null;
45+
}
46+
}

src/Responses/ErrorResponse.php

+18-4
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,32 @@ class ErrorResponse implements Responsable
1414
public function __construct(
1515
public readonly ErrorTypeEnum $errorType,
1616
public readonly string $message,
17+
public readonly ?string $code = null,
18+
public readonly ?string $param = null,
1719
public readonly int $status = 200,
1820
) {
1921
}
2022

2123
public function toResponse($request): Response
2224
{
25+
$error = [
26+
'type' => $this->errorType->value,
27+
'code' => $this->code,
28+
'message' => $this->message,
29+
'param' => $this->param,
30+
];
31+
32+
if (! $this->code) {
33+
unset($error['code']);
34+
}
35+
36+
if (! $this->param) {
37+
unset($error['param']);
38+
}
39+
2340
return new JsonResponse(
2441
data: [
25-
'error' => [
26-
'type' => $this->errorType->value,
27-
'message' => $this->message,
28-
],
42+
'error' => $error,
2943
],
3044
status: $this->status,
3145
);

0 commit comments

Comments
 (0)