required_if
Requires the field to be present and not empty when another field equals one of the given values.
required_if:anotherfield,value,...Parameters
| Parameter | Type | Description |
|---|---|---|
$anotherfield | string | Name of the other field to inspect. Dot notation reaches into nested arrays, and `*` may be used inside an array rule set. |
$value | string | One or more comma-separated values. The field becomes required if anotherfield equals any of them. The literals `true` and `false` are converted to booleans before comparison. |
Errors
Nothing on its own; a failure surfaces as Illuminate\Validation\ValidationException when the rules are run through validate() or a form request.
The field under validation must be present and not empty if the anotherfield field is equal to any value. It is the rule for forms where one answer unlocks another: a credit-card number that is only needed when the payment type is cc, a cancellation reason that is only needed when the status is cancelled.
Comparison is looser than ===
The parameters arrive as strings from the rule name, so Laravel converts the literals true and false into real booleans before comparing. That means required_if:subscribed,true works against a JSON body carrying a genuine true. For the accepted/declined vocabulary ("yes", "on", 1, true) reach for required_if_accepted instead of listing every spelling.
It only controls presence
When the condition is false the field is not required — but it is not removed. If the client sends it anyway, its other rules still run and it still appears in validated(). To actually strip an irrelevant field from the validated payload, use exclude_if or exclude_unless alongside it.
Complex conditions
When the condition is not "another field equals a literal", drop the string rule and use Rule::requiredIf(), which accepts a boolean or a closure returning one.
Example
<?php
use Illuminate\Support\Facades\Validator;
$rules = [
'payment_type' => ['required', 'in:cc,paypal'],
'credit_card_number' => ['required_if:payment_type,cc', 'digits_between:13,19'],
];
$paypal = Validator::make(['payment_type' => 'paypal'], $rules);
$card = Validator::make(['payment_type' => 'cc'], $rules);
var_dump($paypal->passes());
var_dump($card->passes());
print_r($card->errors()->get('credit_card_number'));
// bool(true)
// bool(false)
// Array
// (
// [0] => The credit card number field is required when payment type is cc.
// )When to use it
- Demanding a credit card number only when the chosen payment type is a card.
- Requiring a cancellation reason when an order's status is set to cancelled.
- Asking for a company VAT number only when the account type is business.
- Requiring a shipping address when the delivery method is not in-store pickup.
Frequently asked questions
How do I require a field when a checkbox is ticked?
Use `required_if_accepted:another_field`, which fires when the other field is "yes", "on", 1, "1", true or "true" — the values a checkbox realistically posts. `required_if:another_field,1` works too, but only for the one spelling you listed.
Why is my required_if field still in validated() when the condition was false?
Because required_if only decides whether the field must be present — it never removes it. Any field the client sends that has rules attached appears in validated(). Add `exclude_if` or `exclude_unless` to drop it from the result.
Can required_if depend on more than one field?
Not directly — the colon syntax takes one field and a list of values for it. For multiple conditions use `Rule::requiredIf(fn () => ...)` with a closure, or stack `required_with_all` / `required_without` if the condition is about presence rather than value.
More examples
Rule::requiredIf for conditions the string form cannot express
`Rule::requiredIf` covers everything the colon syntax cannot: the authenticated user's permissions, a database lookup, a feature flag. Prefer the closure form — with the boolean form the expression is evaluated while the rules array is being built, before the validator has seen any input.
<?php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
// A boolean is evaluated immediately.
$validator = Validator::make($request->all(), [
'role_id' => Rule::requiredIf($request->user()->is_admin),
]);
// A closure is deferred until the rule actually runs, which matters
// when the decision depends on something resolved later.
$validator = Validator::make($request->all(), [
'role_id' => Rule::requiredIf(fn () => $request->user()->is_admin),
]);
var_dump($validator->passes());Requiring against a boolean, and stripping the field when it is irrelevant
Swapping `required_if:has_appointment,true` for `exclude_unless:has_appointment,true|required` changes the outcome in one important way: `doctor_name` is dropped from the `validated()` array entirely rather than passed through to your model. `required_if` alone would have kept 'Dr Nobody' in the result.
<?php
use Illuminate\Support\Facades\Validator;
$rules = [
'has_appointment' => ['required', 'boolean'],
'doctor_name' => [
'exclude_unless:has_appointment,true',
'required',
'string',
],
];
$sent = [
'has_appointment' => false,
'doctor_name' => 'Dr Nobody', // irrelevant, sent anyway
];
$validated = Validator::make($sent, $rules)->validate();
print_r($validated);
// Array
// (
// [has_appointment] =>
// )Conditional fields on nested array input
Inside a wildcard rule set, `*` in the referenced field name resolves to the same index as the field being validated, so row 1 is compared against row 1's own method. The message reports the concrete index, which is what makes these errors usable in a repeating form.
<?php
use Illuminate\Support\Facades\Validator;
$input = [
'contacts' => [
['method' => 'email', 'address' => '[email protected]'],
['method' => 'phone', 'address' => null],
],
];
$validator = Validator::make($input, [
'contacts' => ['required', 'array'],
'contacts.*.method' => ['required', 'in:email,phone'],
'contacts.*.address' => ['required_if:contacts.*.method,phone', 'nullable'],
]);
var_dump($validator->passes());
print_r($validator->errors()->toArray());
// bool(false)
// Array
// (
// [contacts.1.address] => Array
// (
// [0] => The contacts.1.address field is required when contacts.1.method is phone.
// )
// )
Discussion