Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
ValidationException
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
7 / 7
15
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getErrors
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getErrorsByField
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 getMessages
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getFirstMessageFor
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
 hasErrorFor
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getFailedFields
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace DevToolbelt\LaravelEloquentPlus\Exceptions;
6
7/**
8 * Exception thrown when model validation fails.
9 *
10 * Contains detailed information about validation errors including
11 * field names, error types, values, and messages.
12 *
13 * @package DevToolbelt\LaravelEloquentPlus\Exceptions
14 */
15class ValidationException extends LaravelEloquentPlusException
16{
17    /**
18     * The validation errors.
19     *
20     * @var array<int, array{field: string, error: string, value: mixed, message: string|null}>
21     */
22    protected array $errors = [];
23
24    /**
25     * Create a new ValidationException instance.
26     *
27     * @param array<int, array{field: string, error: string, value: mixed, message: string|null}> $errors
28     * @param string $message
29     */
30    public function __construct(array $errors, string $message = 'The given data was invalid.')
31    {
32        parent::__construct($message);
33        $this->errors = $errors;
34    }
35
36    /**
37     * Get all validation errors.
38     *
39     * @return array<int, array{field: string, error: string, value: mixed, message: string|null}>
40     */
41    public function getErrors(): array
42    {
43        return $this->errors;
44    }
45
46    /**
47     * Get validation errors grouped by field.
48     *
49     * @return array<string, array<int, array{error: string, value: mixed, message: string|null}>>
50     */
51    public function getErrorsByField(): array
52    {
53        $grouped = [];
54
55        foreach ($this->errors as $error) {
56            $field = $error['field'];
57            unset($error['field']);
58            $grouped[$field][] = $error;
59        }
60
61        return $grouped;
62    }
63
64    /**
65     * Get only the error messages grouped by field.
66     *
67     * @return array<string, array<int, string>>
68     */
69    public function getMessages(): array
70    {
71        $messages = [];
72
73        foreach ($this->errors as $error) {
74            if ($error['message'] !== null) {
75                $messages[$error['field']][] = $error['message'];
76            }
77        }
78
79        return $messages;
80    }
81
82    /**
83     * Get the first error message for a specific field.
84     *
85     * @param string $field
86     * @return string|null
87     */
88    public function getFirstMessageFor(string $field): ?string
89    {
90        foreach ($this->errors as $error) {
91            if ($error['field'] === $field && $error['message'] !== null) {
92                return $error['message'];
93            }
94        }
95
96        return null;
97    }
98
99    /**
100     * Check if a specific field has errors.
101     *
102     * @param string $field
103     * @return bool
104     */
105    public function hasErrorFor(string $field): bool
106    {
107        foreach ($this->errors as $error) {
108            if ($error['field'] === $field) {
109                return true;
110            }
111        }
112
113        return false;
114    }
115
116    /**
117     * Get the list of fields that have errors.
118     *
119     * @return array<int, string>
120     */
121    public function getFailedFields(): array
122    {
123        return array_unique(array_column($this->errors, 'field'));
124    }
125}