Skip to content

Commit 33b94e1

Browse files
authored
Merge pull request #16 from rakit/array-validation
Feature: Array Validation
2 parents e65c173 + f6d40c8 commit 33b94e1

24 files changed

+1128
-249
lines changed

README.md

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,30 @@ use Rakit\Validation\Validator;
3838
$validator = new Validator;
3939

4040
// make it
41-
$validation = $validator->make($_POST, [
42-
'name' => 'required',
43-
'email' => 'required|email',
44-
'password' => 'required|min:6',
45-
'confirm_password' => 'required|same:password',
41+
$validation = $validator->make($_POST + $_FILES, [
42+
'name' => 'required',
43+
'email' => 'required|email',
44+
'password' => 'required|min:6',
45+
'confirm_password' => 'required|same:password',
46+
'avatar' => 'required|uploaded_file:0,500K,png,jpeg',
47+
'skills' => 'array',
48+
'skills.*.id' => 'required|numeric',
49+
'skills.*.percentage' => 'required|numeric'
4650
]);
4751

4852
// then validate
4953
$validation->validate();
5054

5155
if ($validation->fails()) {
52-
// handling errors
53-
$errors = $validation->errors();
54-
echo "<pre>";
55-
print_r($errors->firstOfAll());
56-
echo "</pre>";
57-
exit;
56+
// handling errors
57+
$errors = $validation->errors();
58+
echo "<pre>";
59+
print_r($errors->firstOfAll());
60+
echo "</pre>";
61+
exit;
5862
} else {
59-
// validation passes
60-
echo "Success!";
63+
// validation passes
64+
echo "Success!";
6165
}
6266

6367
```
@@ -73,11 +77,15 @@ use Rakit\Validation\Validator;
7377

7478
$validator = new Validator;
7579

76-
$validation = $validator->validate($_POST, [
77-
'name' => 'required',
78-
'email' => 'required|email',
79-
'password' => 'required|min:6',
80-
'confirm_password' => 'required|same:password',
80+
$validation = $validator->validate($_POST + $_FILES, [
81+
'name' => 'required',
82+
'email' => 'required|email',
83+
'password' => 'required|min:6',
84+
'confirm_password' => 'required|same:password',
85+
'avatar' => 'required|uploaded_file:0,500K,png,jpeg',
86+
'skills' => 'array',
87+
'skills.*.id' => 'required|numeric',
88+
'skills.*.percentage' => 'required|numeric'
8189
]);
8290

8391
if ($validation->fails()) {
@@ -94,7 +102,7 @@ if ($validation->fails()) {
94102

95103
```
96104

97-
In this case, 2 example above will output the same results.
105+
In this case, 2 examples above will output the same results.
98106

99107
But with `make` you can setup something like custom invalid message, custom attribute alias, etc before validation running.
100108

@@ -217,7 +225,7 @@ $validation_a->validate();
217225
#### Custom Message for Specific Attribute Rule
218226

219227
Sometimes you may want to set custom message for specific rule attribute.
220-
To do this you can use `.` as message separator or using chaining method.
228+
To do this you can use `:` as message separator or using chaining methods.
221229

222230
Examples:
223231

@@ -229,7 +237,7 @@ $validation_a = $validator->make($dataset_a, [
229237
]);
230238

231239
$validation_a->setMessages([
232-
'age.min' => '18+ only',
240+
'age:min' => '18+ only',
233241
]);
234242

235243
$validation_a->validate();
@@ -523,7 +531,7 @@ $validation = $validator->validate($_POST, [
523531
]);
524532
```
525533

526-
In `UniqueRule` above, property `$message` is used for default invalid message. And property `$fillable_params` is used for `setParameters` method (defined in `Rakit\Validation\Rule` class). By default `setParameters` will fill parameters listed in `$fillable_params`. For example `unique:users,email,[email protected]` in example above, will set:
534+
In `UniqueRule` above, property `$message` is used for default invalid message. And property `$fillable_params` is used for `fillParameters` method (defined in `Rakit\Validation\Rule` class). By default `fillParameters` will fill parameters listed in `$fillable_params`. For example `unique:users,email,[email protected]` in example above, will set:
527535

528536
```php
529537
$params['table'] = 'users';
@@ -532,7 +540,7 @@ $params['except'] = '[email protected]';
532540
```
533541

534542
> If you want your custom rule accept parameter list like `in`,`not_in`, or `uploaded_file` rules,
535-
you just need to override `setParameters(array $params)` method in your custom rule class.
543+
you just need to override `fillParameters(array $params)` method in your custom rule class.
536544

537545
Note that `unique` rule that we created above also can be used like this:
538546

src/Attribute.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class Attribute
1515

1616
protected $required = false;
1717

18+
protected $primaryAttribute = null;
19+
20+
protected $otherAttributes = [];
21+
1822
public function __construct(Validation $validation, $key, $alias = null, array $rules = array())
1923
{
2024
$this->validation = $validation;
@@ -25,6 +29,34 @@ public function __construct(Validation $validation, $key, $alias = null, array $
2529
}
2630
}
2731

32+
public function setPrimaryAttribute(Attribute $primaryAttribute)
33+
{
34+
$this->primaryAttribute = $primaryAttribute;
35+
}
36+
37+
public function getPrimaryAttribute()
38+
{
39+
return $this->primaryAttribute;
40+
}
41+
42+
public function setOtherAttributes(array $otherAttributes)
43+
{
44+
$this->otherAttributes = [];
45+
foreach($otherAttributes as $otherAttribute) {
46+
$this->addOtherAttribute($otherAttribute);
47+
}
48+
}
49+
50+
public function addOtherAttribute(Attribute $otherAttribute)
51+
{
52+
$this->otherAttributes[] = $otherAttribute;
53+
}
54+
55+
public function getOtherAttributes()
56+
{
57+
return $this->otherAttributes;
58+
}
59+
2860
public function addRule(Rule $rule)
2961
{
3062
$rule->setAttribute($this);

src/ErrorBag.php

Lines changed: 103 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,58 +26,132 @@ public function count()
2626
return count($this->all());
2727
}
2828

29-
public function first($key)
29+
public function has($key)
3030
{
31-
if (empty($this->messages[$key])) return null;
32-
return array_values($this->messages[$key])[0];
31+
list($key, $ruleName) = $this->parsekey($key);
32+
if ($this->isWildcardKey($key)) {
33+
$messages = $this->filterMessagesForWildcardKey($key, $ruleName);
34+
return count(Helper::arrayDot($messages)) > 0;
35+
} else {
36+
$messages = isset($this->messages[$key])? $this->messages[$key] : null;
37+
38+
if (!$ruleName) {
39+
return !empty($messages);
40+
} else {
41+
return !empty($messages) AND isset($messages[$ruleName]);
42+
}
43+
}
3344
}
3445

35-
public function last($key)
46+
public function first($key)
3647
{
37-
if (empty($this->messages[$key])) return null;
38-
return array_values($this->messages[$key])[count($this->messages[$key])-1];
48+
list($key, $ruleName) = $this->parsekey($key);
49+
if ($this->isWildcardKey($key)) {
50+
$messages = $this->filterMessagesForWildcardKey($key, $ruleName);
51+
$flattenMessages = Helper::arrayDot($messages);
52+
return array_shift($flattenMessages);
53+
} else {
54+
$keyMessages = isset($this->messages[$key])? $this->messages[$key] : [];
55+
56+
if (empty($keyMessages)) {
57+
return null;
58+
}
59+
60+
if ($ruleName) {
61+
return isset($keyMessages[$ruleName])? $keyMessages[$ruleName] : null;
62+
} else {
63+
return array_shift($keyMessages);
64+
}
65+
}
3966
}
4067

41-
public function get($key, $rule)
68+
public function get($key, $format = ':message')
4269
{
43-
if (empty($this->messages[$key])) return null;
44-
if (empty($this->messages[$key][$rule])) return null;
45-
return $this->messages[$key][$rule];
70+
list($key, $ruleName) = $this->parsekey($key);
71+
$results = [];
72+
if ($this->isWildcardKey($key)) {
73+
$messages = $this->filterMessagesForWildcardKey($key, $ruleName);
74+
foreach($messages as $explicitKey => $keyMessages) {
75+
foreach ($keyMessages as $rule => $message) {
76+
$results[$explicitKey][$rule] = $this->formatMessage($message, $format);
77+
}
78+
}
79+
} else {
80+
$keyMessages = isset($this->messages[$key])? $this->messages[$key] : [];
81+
foreach($keyMessages as $rule => $message) {
82+
if ($ruleName AND $ruleName != $rule) continue;
83+
$results[$rule] = $this->formatMessage($message, $format);
84+
}
85+
}
86+
87+
return $results;
4688
}
4789

4890
public function all($format = ':message')
4991
{
50-
$messages = [];
51-
foreach($this->messages as $key => $keyMessages) {
52-
foreach($keyMessages as $msg) {
53-
$messages[] = str_replace(':message', $format, $msg);
92+
$messages = $this->messages;
93+
$results = [];
94+
foreach($messages as $key => $keyMessages) {
95+
foreach($keyMessages as $message) {
96+
$results[] = $this->formatMessage($message, $format);
5497
}
5598
}
99+
return $results;
100+
}
101+
102+
public function firstOfAll($format = ':message')
103+
{
104+
$messages = $this->messages;
105+
$results = [];
106+
foreach($messages as $key => $keyMessages) {
107+
$results[] = $this->formatMessage(array_shift($messages[$key]), $format);
108+
}
109+
return $results;
110+
}
56111

57-
return $messages;
112+
public function toArray()
113+
{
114+
return $this->messages;
58115
}
59116

60-
public function implode($glue, $format = ':message')
117+
protected function parseKey($key)
61118
{
62-
return implode($glue, $this->all($format));
119+
$expl = explode(':', $key, 2);
120+
$key = $expl[0];
121+
$ruleName = isset($expl[1])? $expl[1] : null;
122+
return [$key, $ruleName];
63123
}
64124

65-
public function firstOfAll()
125+
protected function isWildcardKey($key)
66126
{
67-
$messages = [];
68-
foreach($this->messages as $key => $keyMessages) {
69-
$messages[] = $this->first($key);
70-
}
71-
return $messages;
127+
return false !== strpos($key, '*');
72128
}
73129

74-
public function lastOfAll()
130+
protected function filterMessagesForWildcardKey($key, $ruleName = null)
75131
{
76-
$messages = [];
77-
foreach($this->messages as $key => $keyMessages) {
78-
$messages[] = $this->last($key);
132+
$messages = $this->messages;
133+
$pattern = preg_quote($key, '#');
134+
$pattern = str_replace('\*', '.*', $pattern);
135+
136+
$filteredMessages = [];
137+
138+
foreach ($messages as $k => $keyMessages) {
139+
if ((bool) preg_match('#^'.$pattern.'\z#u', $k) === false) {
140+
continue;
141+
}
142+
143+
foreach($keyMessages as $rule => $message) {
144+
if ($ruleName AND $rule != $ruleName) continue;
145+
$filteredMessages[$k][$rule] = $message;
146+
}
79147
}
80-
return $messages;
148+
149+
return $filteredMessages;
150+
}
151+
152+
protected function formatMessage($message, $format)
153+
{
154+
return str_replace(':message', $message, $format);
81155
}
82156

83-
}
157+
}

0 commit comments

Comments
 (0)