Skip to content

Commit

Permalink
Add requires rule to force another field to be present
Browse files Browse the repository at this point in the history
  • Loading branch information
dave-redfern committed Jun 15, 2024
1 parent f5b1fcb commit 66acb90
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Change Log
==========

2024-06-15
----------

* add `requires` rule to ensure field(s) are present when another field is provided
* improve documentation of `required_with`

2024-05-31
----------

Expand Down
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -769,10 +769,28 @@ The field under validation must be present and not empty unless the `another_fie

</details>

<details><summary><strong>requires</strong>:field_1,field_2,...</summary>

The field under validation requires that the specified fields are present in the input data and are not empty.

For example: field b "requires:a"; if a is either not present, or has an "empty" value, then the validation
fails. "empty" is false, empty string, or null.

This is an extension of `required_with`, however the rule will fail when used with `sometimes` or `nullable`.
For example: if b "requires:a" and "a" is allowed to be `nullable`, b will fail as it explicitly requires a
with a value.

</details>

<details><summary><strong>required_with</strong>:field_1,field_2,...</summary>

The field under validation must be present and not empty only if any of the other specified fields are present.

__Note__: the behaviour of this rule can be circumvented if the rule this is defined on is `sometimes` or
`nullable`. For example: if a is "required_with:b", but a is also only `sometimes` present, then the required_with
will never trigger as the sometimes rule will negate it. a would also need to be explicitly passed to trigger the
rule.

</details>

<details><summary><strong>required_without</strong>:field_1,field_2,...</summary>
Expand All @@ -783,13 +801,13 @@ The field under validation must be present and not empty only when any of the ot

<details><summary><strong>required_with_all</strong>:field_1,field_2,...</summary>

The field under validation must be present and not empty only if all of the other specified fields are present.
The field under validation must be present and not empty only if all the other specified fields are present.

</details>

<details><summary><strong>required_without_all</strong>:field_1,field_2,...</summary>

The field under validation must be present and not empty only when all of the other specified fields are not present.
The field under validation must be present and not empty only when all the other specified fields are not present.

</details>

Expand Down
1 change: 1 addition & 0 deletions src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ protected function registerDefaultRules(): void
'regex' => new Rules\Regex,
'rejected' => new Rules\Rejected,
'required' => new Rules\Required,
'requires' => new Rules\Requires,
'required_if' => new Rules\RequiredIf,
'required_unless' => new Rules\RequiredUnless,
'required_with' => new Rules\RequiredWith,
Expand Down
1 change: 1 addition & 0 deletions src/Resources/i18n/en.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
'rule.regex' => ':attribute does not meet required format',
'rule.rejected' => ':attribute must be one of: :rejected',
'rule.required' => ':attribute is required',
'rule.requires' => ':attribute requires :fields',
'rule.required_if' => ':attribute is required if :field has a value of :values',
'rule.required_unless' => ':attribute is required if :fields has one of :values',
'rule.required_with' => ':attribute is required with :fields',
Expand Down
31 changes: 31 additions & 0 deletions src/Rules/Requires.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php declare(strict_types=1);

namespace Somnambulist\Components\Validation\Rules;

class Requires extends Required
{
protected bool $implicit = true;
protected string $message = 'rule.requires';

public function fillParameters(array $params): self
{
$this->params['fields'] = $params;

return $this;
}

public function check(mixed $value): bool
{
$this->assertHasRequiredParameters(['fields']);

$fields = $this->parameter('fields');

foreach ($fields as $field) {
if (!$this->validation->input()->has($field) || empty($this->validation->input()->get($field))) {
return false;
}
}

return true;
}
}
37 changes: 37 additions & 0 deletions tests/Rules/RequiredRulesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,43 @@ public function testRequiredUnlessRule()
$this->assertTrue($v2->passes());
}

public function testRequiresRule()
{
$v1 = $this->validator->validate([
'b' => '',
], [
'b' => 'requires:a'
]);

$this->assertFalse($v1->passes());

$v2 = $this->validator->validate([
'a' => '',
'b' => '',
], [
'b' => 'requires:a'
]);

$this->assertFalse($v2->passes());

$v3 = $this->validator->validate([
'a' => null,
'b' => '',
], [
'b' => 'requires:a'
]);

$this->assertFalse($v3->passes());

$v4 = $this->validator->validate([
'a' => '23',
'b' => '',
], [
'b' => 'requires:a'
]);
$this->assertTrue($v4->passes());
}

public function testRequiredWithRule()
{
$v1 = $this->validator->validate([
Expand Down

0 comments on commit 66acb90

Please sign in to comment.