Skip to content

Cannot use multiple requiring rules #647

Open
@striker4150

Description

@striker4150

✏️ Describe the bug
Adding multiple requiring rules to a property/parameter only results in the last added requiring rule being applied. For example, if a RequiredUnless rule is used alongside a RequiredWith rule, only the RequiredWith rule will be applied (assuming that the RequiredWith rule is last).

The offending lines seem to be:

$this->rules = $this->rules->reject(function (ValidationRule $rule) use ($classes) {
foreach ($classes as $class) {
if ($class instanceof RequiringRule && $rule instanceof RequiringRule) {
return true;
}

↪️ To Reproduce

it('cannot add multiple requiring rules', function () {
    class BaseData extends Data
    {
        public function __construct(
            #[RequiredUnless('requires_a', false), RequiredWith('b')]
            public string $a,
            public string $b,
            public bool $requires_a,
        ) {
        }
    }

    dd(BaseData::getValidationRules([]));
});

✅ Expected behavior
In the scenario above, I expect the a property to have the requiring rules ['required_unless:requires_a,false', 'required_with:b']. However, the a property only has the required_with:b. Laravel does offer the ability to apply multiple requiring rules at once, as demonstrated here:

Validator::make(
  [
    "a" => "a",
    "b" => "b",
    "requires_a" => false
  ],
  [
    "a" => ["required_unless:requires_a,false", "required_with:b"]
  ]
)->passes();
// Returns true

Validator::make(
  [
    "a" => "",
    "b" => "b",
    "requires_a" => true
  ],
  [
    "a" => ["required_unless:requires_a,false", "required_with:b"]
  ]
)->passes();
// Returns false (it's required with b AND requires_a is true)

Validator::make(
  [
    "a" => "",
    "b" => "b",
    "requires_a" => false,
  ],
  [
    "a" => ["required_unless:requires_a,false", "required_with:b"]
  ]
)->passes();
// Returns false (it's required with b)

Validator::make(
  [
    "a" => "",
    "b" => "",
    "requires_a" => true,
  ],
  [
    "a" => ["required_unless:requires_a,false", "required_with:b"]
  ]
)->passes();
// Returns false (requires_a is true)

Validator::make(
  [
    "a" => "",
    "b" => "",
    "requires_a" => false
  ],
  [
    "a" => ["required_unless:requires_a,false", "required_with:b"]
  ]
)->passes();
// Returns true

I expect requiring rules to be applied even if they are of the same type. The only requiring rule that I would expect to not be duplicated is the plain Required rule.

🖥️ Versions

Laravel: 10.x
Laravel Data: 3.11.0
PHP: 8.1.15

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions