Skip to content

Commit 9720193

Browse files
authored
Added exclude rules for hyperf/validation (#7148)
1 parent 917eb70 commit 9720193

File tree

5 files changed

+325
-3
lines changed

5 files changed

+325
-3
lines changed

publish/en/validation.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@
111111
'required_with_all' => 'The :attribute field is required when :values is present.',
112112
'required_without' => 'The :attribute field is required when :values is not present.',
113113
'required_without_all' => 'The :attribute field is required when none of :values are present.',
114+
'exclude' => 'The :attribute field is excluded.',
115+
'exclude_if' => 'The :attribute field is excluded when :other is :value.',
116+
'exclude_unless' => 'The :attribute field is excluded unless :other is in :values.',
117+
'exclude_with' => 'The :attribute field is excluded when :values is present.',
118+
'exclude_without' => 'The :attribute field is excluded when :values is not present.',
114119
'same' => 'The :attribute and :other must match.',
115120
'size' => [
116121
'numeric' => 'The :attribute must be :size.',

publish/zh_CN/validation.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@
111111
'required_with_all' => ':attribute 字段是必须的当 :values 是存在的',
112112
'required_without' => ':attribute 字段是必须的当 :values 是不存在的',
113113
'required_without_all' => ':attribute 字段是必须的当 没有一个 :values 是存在的',
114+
'exclude' => ':attribute 字段是被排除的',
115+
'exclude_if' => '当 :other 为 :value 时,排除 :attribute 字段',
116+
'exclude_unless' => '除非 :other 是在 :values 中,否则排除 :attribute 字段',
117+
'exclude_with' => '当 :values 存在时,排除 :attribute 字段',
118+
'exclude_without' => '当 :values 不存在时,排除 :attribute 字段',
114119
'same' => ':attribute 和 :other 必须匹配',
115120
'size' => [
116121
'numeric' => ':attribute 必须是 :size',

src/Concerns/ValidatesAttributes.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,46 @@ public function validateRequiredIf(string $attribute, $value, array $parameters)
12971297
return true;
12981298
}
12991299

1300+
/**
1301+
* Indicate that an attribute is excluded.
1302+
*/
1303+
public function validateExclude(): bool
1304+
{
1305+
return false;
1306+
}
1307+
1308+
/**
1309+
* Indicate that an attribute should be excluded when another attribute has a given value.
1310+
*
1311+
* @param mixed $value
1312+
*/
1313+
public function validateExcludeIf(string $attribute, $value, array $parameters): bool
1314+
{
1315+
$this->requireParameterCount(2, $parameters, 'exclude_if');
1316+
1317+
if (! Arr::has($this->data, $parameters[0])) {
1318+
return true;
1319+
}
1320+
1321+
[$values, $other] = $this->parseDependentRuleParameters($parameters);
1322+
1323+
return ! in_array($other, $values, is_bool($other) || is_null($other));
1324+
}
1325+
1326+
/**
1327+
* Indicate that an attribute should be excluded when another attribute does not have a given value.
1328+
*
1329+
* @param mixed $value
1330+
*/
1331+
public function validateExcludeUnless(string $attribute, $value, array $parameters): bool
1332+
{
1333+
$this->requireParameterCount(2, $parameters, 'exclude_unless');
1334+
1335+
[$values, $other] = $this->parseDependentRuleParameters($parameters);
1336+
1337+
return in_array($other, $values, is_bool($other) || is_null($other));
1338+
}
1339+
13001340
/**
13011341
* Validate that an attribute exists when another attribute does not have a given value.
13021342
*
@@ -1317,6 +1357,38 @@ public function validateRequiredUnless(string $attribute, $value, array $paramet
13171357
return true;
13181358
}
13191359

1360+
/**
1361+
* Indicate that an attribute should be excluded when another attribute presents.
1362+
*
1363+
* @param mixed $value
1364+
*/
1365+
public function validateExcludeWith(string $attribute, $value, array $parameters): bool
1366+
{
1367+
$this->requireParameterCount(1, $parameters, 'exclude_with');
1368+
1369+
if (! Arr::has($this->data, $parameters[0])) {
1370+
return true;
1371+
}
1372+
1373+
return false;
1374+
}
1375+
1376+
/**
1377+
* Indicate that an attribute should be excluded when another attribute is missing.
1378+
*
1379+
* @param mixed $value
1380+
*/
1381+
public function validateExcludeWithout(string $attribute, $value, array $parameters): bool
1382+
{
1383+
$this->requireParameterCount(1, $parameters, 'exclude_without');
1384+
1385+
if ($this->anyFailingRequired($parameters)) {
1386+
return false;
1387+
}
1388+
1389+
return true;
1390+
}
1391+
13201392
/**
13211393
* Validate that an attribute exists when any other attribute exists.
13221394
*

src/Validator.php

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ class Validator implements ValidatorContract
5252
*/
5353
public array $customValues = [];
5454

55+
/**
56+
* Indicates that unvalidated array keys should be excluded, even if the parent array was validated.
57+
*/
58+
public bool $excludeUnvalidatedArrayKeys = false;
59+
5560
/**
5661
* All the custom validator extensions.
5762
*/
@@ -77,6 +82,11 @@ class Validator implements ValidatorContract
7782
*/
7883
protected array $failedRules = [];
7984

85+
/**
86+
* Attributes that should be excluded from the validated data.
87+
*/
88+
protected array $excludeAttributes = [];
89+
8090
/**
8191
* The message bag instance.
8292
*/
@@ -137,9 +147,14 @@ class Validator implements ValidatorContract
137147
'RequiredWith', 'RequiredWithAll', 'RequiredWithout', 'RequiredWithoutAll',
138148
'RequiredIf', 'RequiredUnless', 'Confirmed', 'Same', 'Different', 'Unique',
139149
'Before', 'After', 'BeforeOrEqual', 'AfterOrEqual', 'Gt', 'Lt', 'Gte', 'Lte',
140-
'Prohibits',
150+
'Prohibits', 'ExcludeIf', 'ExcludeUnless', 'ExcludeWith', 'ExcludeWithout',
141151
];
142152

153+
/**
154+
* The validation rules that can exclude an attribute.
155+
*/
156+
protected array $excludeRules = ['Exclude', 'ExcludeIf', 'ExcludeUnless', 'ExcludeWith', 'ExcludeWithout'];
157+
143158
/**
144159
* The size related validation rules.
145160
*/
@@ -242,9 +257,19 @@ public function passes(): bool
242257
foreach ($this->rules as $attribute => $rules) {
243258
$attribute = str_replace('\.', '->', $attribute);
244259

260+
if ($this->shouldBeExcluded($attribute)) {
261+
$this->removeAttribute($attribute);
262+
263+
continue;
264+
}
265+
245266
foreach ($rules as $rule) {
246267
$this->validateAttribute($attribute, $rule);
247268

269+
if ($this->shouldBeExcluded($attribute)) {
270+
break;
271+
}
272+
248273
if ($this->shouldStopValidating($attribute)) {
249274
break;
250275
}
@@ -298,9 +323,16 @@ public function validated(): array
298323

299324
$missingValue = Str::random(10);
300325

301-
foreach (array_keys($this->getRules()) as $key) {
326+
foreach ($this->getRules() as $key => $rules) {
302327
$value = data_get($this->getData(), $key, $missingValue);
303328

329+
if ($this->excludeUnvalidatedArrayKeys
330+
&& (in_array('array', $rules) || in_array('list', $rules))
331+
&& $value !== null
332+
&& ! empty(preg_grep('/^' . preg_quote($key, '/') . '\.+/', array_keys($this->getRules())))) {
333+
continue;
334+
}
335+
304336
if ($value !== $missingValue) {
305337
Arr::set($results, $key, $value);
306338
}
@@ -312,12 +344,17 @@ public function validated(): array
312344
/**
313345
* Add a failed rule and error message to the collection.
314346
*/
315-
public function addFailure(string $attribute, string $rule, array $parameters = [])
347+
public function addFailure(string $attribute, string $rule, array $parameters = []): void
316348
{
317349
if (! $this->messages) {
318350
$this->passes();
319351
}
320352

353+
if (in_array($rule, $this->excludeRules)) {
354+
$this->excludeAttribute($attribute);
355+
return;
356+
}
357+
321358
$this->messages->add($attribute, $this->makeReplacements(
322359
$this->getMessage($attribute, $rule),
323360
$attribute,
@@ -720,6 +757,31 @@ public function setValue($attribute, $value)
720757
Arr::set($this->data, $attribute, $value);
721758
}
722759

760+
/**
761+
* Determine if the attribute should be excluded.
762+
*/
763+
protected function shouldBeExcluded(string $attribute): bool
764+
{
765+
foreach ($this->excludeAttributes as $excludeAttribute) {
766+
if ($attribute === $excludeAttribute
767+
|| Str::startsWith($attribute, $excludeAttribute . '.')) {
768+
return true;
769+
}
770+
}
771+
772+
return false;
773+
}
774+
775+
/**
776+
* Add the given attribute to the list of excluded attributes.
777+
*/
778+
protected function excludeAttribute(string $attribute): void
779+
{
780+
$this->excludeAttributes[] = $attribute;
781+
782+
$this->excludeAttributes = array_unique($this->excludeAttributes);
783+
}
784+
723785
/**
724786
* Validate a given attribute against a rule.
725787
*
@@ -832,6 +894,10 @@ protected function replaceAsterisksInParameters(array $parameters, array $keys):
832894
*/
833895
protected function isValidatable($rule, string $attribute, $value): bool
834896
{
897+
if (in_array($rule, $this->excludeRules)) {
898+
return true;
899+
}
900+
835901
return $this->presentOrRuleIsImplicit($rule, $attribute, $value)
836902
&& $this->passesOptionalCheck($attribute)
837903
&& $this->isNotNullIfMarkedAsNullable($rule, $attribute)

0 commit comments

Comments
 (0)