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{
28     *     field: string,
29     *     error: string,
30     *     value: mixed,
31     *     message: string|null
32     * }> $errors
33     * @param string $message
34     */
35    public function __construct(array $errors, string $message = 'The given data was invalid.')
36    {
37        parent::__construct($message);
38        $this->errors = $errors;
39    }
40
41    /**
42     * Get all validation errors.
43     *
44     * @return array<int, array{field: string, error: string, value: mixed, message: string|null}>
45     */
46    public function getErrors(): array
47    {
48        return $this->errors;
49    }
50
51    /**
52     * Get validation errors grouped by field.
53     *
54     * @return array<string, array<int, array{error: string, value: mixed, message: string|null}>>
55     */
56    public function getErrorsByField(): array
57    {
58        $grouped = [];
59
60        foreach ($this->errors as $error) {
61            $field = $error['field'];
62            unset($error['field']);
63            $grouped[$field][] = $error;
64        }
65
66        return $grouped;
67    }
68
69    /**
70     * Get only the error messages grouped by field.
71     *
72     * @return array<string, array<int, string>>
73     */
74    public function getMessages(): array
75    {
76        $messages = [];
77
78        foreach ($this->errors as $error) {
79            if ($error['message'] !== null) {
80                $messages[$error['field']][] = $error['message'];
81            }
82        }
83
84        return $messages;
85    }
86
87    /**
88     * Get the first error message for a specific field.
89     *
90     * @param string $field
91     * @return string|null
92     */
93    public function getFirstMessageFor(string $field): ?string
94    {
95        foreach ($this->errors as $error) {
96            if ($error['field'] === $field && $error['message'] !== null) {
97                return $error['message'];
98            }
99        }
100
101        return null;
102    }
103
104    /**
105     * Check if a specific field has errors.
106     *
107     * @param string $field
108     * @return bool
109     */
110    public function hasErrorFor(string $field): bool
111    {
112        foreach ($this->errors as $error) {
113            if ($error['field'] === $field) {
114                return true;
115            }
116        }
117
118        return false;
119    }
120
121    /**
122     * Get the list of fields that have errors.
123     *
124     * @return array<int, string>
125     */
126    public function getFailedFields(): array
127    {
128        return array_unique(array_column($this->errors, 'field'));
129    }
130}