phpvalidationlaravellaravel-4laravel-validation

Laravel validation: exists with additional column condition - custom validation rule


Is there is a way of referencing another field when specifying the exists validation rule in Laravel? I want to be able to say that input a must exist in table a, input b must exist in table b AND the value for column x in table b must equal input a.

Best explained by example:

public $rules = array(
    'game_id' => 'required|exists:games,id',
    'team1_id' => 'required|exists:teams,id,game_id,<game_id input value here>',
    'team2_id' => 'required|exists:teams,id,game_id,<game_id input value here>'
);

So with my validation rules I want to be able to make sure that:

So, if in my form, I entered 1 for game_id, I want to be able to ensure that the record within the teams table for both team1_id and team2_id have the value 1 for game_id.

I hope this makes sense.

Thanks


Solution

  • You want a custom validation rule, and I would create a separate class for this. But for brevity here's pretty much the same using inline closure:

    // give it meaningful name, I'll go with game_fixture as an example
    Validator::extend('game_fixture', function ($attribute, $value, $parameters, $validator) 
    {
        if (count($parameters) < 4)
        {
            throw new \InvalidArgumentException("Validation rule game_fixture requires 4 parameters.");
        }
    
        $input    = $validator->getData();
        $verifier = $validator->getPresenceVerifier();
    
        $collection = $parameters[0];
        $column     = $parameters[1];
        $extra      = [$parameters[2] => array_get($input, $parameters[3])];
    
        $count = $verifier->getMultiCount($collection, $column, (array) $value, $extra);
    
        return $count >= 1;
    });
    

    Then use simply this:

    $rules = array(
        'game_id' => 'required|exists:games,id',
    
        // last parameter here refers to the 'game_id' value passed to the validator
        'team1_id' => 'required|game_fixture:teams,id,game_id,game_id',
        'team2_id' => 'required|game_fixture:teams,id,game_id,game_id'
    );