Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Using the Laravel Validator, make a field required if another field is set to a given attribute.

Setup

  • Add this file to application/libraries (or, if you are already extending the Validator class, add the contents there).
  • Remove Validator alias from config/application.php in order to avoid conflicts.
  • Add "required_if_attribute" => "The :attribute field is required." to application/language/[language]/validation.php.

Usage

Define the rule using:

required_if_attribute:[field],[operator],[value]

For example:

$rules = array(
    'uses_framework' => 'required',
    'preferred_framework' => 'required_if_attribute:uses_framework,==,1'
);

Supported operators

  • ==
  • !=
  • ===
  • !==
  • <
  • <=
  • =

This is, of course, easily extended.

<?php
/**
* Validator
*
* Extending the Laravel Validator class allows us to define more powerful validation functions than
* with the Validator::register method.
*/
class Validator extends Laravel\Validator {
/**
* Implicit Attributes
*
* Attributes with these rules will be validated even if no value is supplied.
*/
protected $implicit_attributes = array(
'required',
'accepted',
'required_if_attribute'
);
/**
* Implicit
*
* By default Laravel will only validate an attribute if a value was supplied, or if the rule set is 'required' or 'accepted'.
* It'll just skip the validation, which makes 'require' being conditional impossible. Let's overwrite that to be more flexible.
*/
protected function implicit($rule) {
return (in_array($rule, $this->implicit_attributes));
}
/**
* Required if attribute
*
* Validate that a required attribute exists, only if another
* attribute satisfies the supplied conditions.
*
* i.e. 'What is your favourite PHP framework?' is only required if
* 'Do you use a framework?' is set to '1'.
*/
public function validate_required_if_attribute($attribute, $value, $parameters) {
$required = false;
switch($parameters[1]) {
case '==':
$required = $this->attributes[$parameters[0]] == $parameters[2];
case '!=':
$required = $this->attributes[$parameters[0]] != $parameters[2];
case '===':
$required = $this->attributes[$parameters[0]] === $parameters[2];
case '!==':
$required = $this->attributes[$parameters[0]] !== $parameters[2];
case '<':
$required = $this->attributes[$parameters[0]] < $parameters[2];
case '<=':
$required = $this->attributes[$parameters[0]] <= $parameters[2];
case '>':
$required = $this->attributes[$parameters[0]] > $parameters[2];
case '>=':
$required = $this->attributes[$parameters[0]] >= $parameters[2];
}
return $required ? $this->validate_required($attribute, $value) : true;
}
}
?>
@Ardakilic
Copy link

Awesome, I was writing something like this from scratch for my project, then googling brought me here, nicely coded, thanks!

@r-patrik
Copy link

r-patrik commented May 5, 2013

I think break; -s needed after all case... but great! Thanks!

@juice49
Copy link
Author

juice49 commented Nov 30, 2013

@Ardakilic @PaddyHu Glad this helped you (:

@stefandoorn
Copy link

Trying to make this work in Laravel 4.1 I had to change some points:

  • $this->attributes to be replaced with $this->data
  • Inserted breaks as it was breaking my checks
  • Replaced $this->validate_required with $this->validateRequired

New code:

public function validateRequiredIfAttribute($attribute, $value, $parameters) 
{

    $required = false;

    switch($parameters[1]) 
    {

        case '==':
            $required = $this->data[$parameters[0]] == $parameters[2];
            break;
        case '!=':
            $required = $this->data[$parameters[0]] != $parameters[2];
            break;
        case '===':
            $required = $this->data[$parameters[0]] === $parameters[2];
            break;
        case '!==':
            $required = $this->data[$parameters[0]] !== $parameters[2];
            break;
        case '<':
            $required = $this->data[$parameters[0]] < $parameters[2];
            break;
        case '<=':
            $required = $this->data[$parameters[0]] <= $parameters[2];
            break;
        case '>':
            $required = $this->data[$parameters[0]] > $parameters[2];
            break;
        case '>=':
            $required = $this->data[$parameters[0]] >= $parameters[2];
            break;
    }

    return $required ? $this->validateRequired($attribute, $value) : true;

}

@hansvn
Copy link

hansvn commented Jul 22, 2014

I'm always getting this error: Undefined property: CustomValidator::$data when trying to use this validator... I also tried $this->getAttribute($parameters[0]) but this gives me the same error...
Why is this not working with me (I'm using Laravel 4.2) ?
maybe could somebody provide an example?

@giopetris
Copy link

Hello hansvn, in Laravel 4.1 you can use validator "required_if:field,value"

@benedict-w
Copy link

Very useful. Thanks! The switch-case is missing break statements though ;)

@MonrealRyan
Copy link

What About in 4.2? Thank a lot.

@gthuo
Copy link

gthuo commented Feb 24, 2018

Glad it is now covered in Laravel by default: required_if:field,value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment