web-dev-qa-db-fra.com

Laravel validation: existe avec condition de colonne supplémentaire - règle de validation personnalisée

Existe-t-il un moyen de référencer un autre champ lors de la spécification de la règle de validation existante dans Laravel? Je veux pouvoir dire que l'entrée a doit exister dans le tableau a, que l'entrée b doit exister dans le tableau b ET que la valeur de la colonne x du tableau b doit être égale à l'entrée a.

Mieux expliqué par exemple:

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>'
);

Donc, avec mes règles de validation, je veux pouvoir être sûr que:

  • game_id existe dans la table games (champ id)
  • team1_id existe dans la table teams (champ id) et la colonne game_id (dans la table teams) doit être égale à la valeur de l'entrée game_id.
  • Comme ci-dessus pour team2_id

Donc, si dans mon formulaire, j'ai entré 1 pour game_id, je veux pouvoir vérifier que l'enregistrement dans la table des équipes pour team1_id et team2_id a la valeur 1 pour game_id.

J'espère que cela a du sens.

Merci

10
Jonathon

Vous voulez une règle de validation personnalisée , et je créerais une classe distincte pour cela. Mais pour être bref, voici à peu près la même chose avec la fermeture en ligne:

// 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;
});

Ensuite, utilisez simplement ceci:

$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'
);
9
Jarek Tkaczyk

EDIT: Soi-disant, cela ne fonctionne pas dans Laravel 5.5. @ user3151197 answer pourrait faire l'affaire.

J'utilise Laravel 5.4 et il a la possibilité d'ajouter une règle personnalisée Rule aux règles existantes et uniques. Je pense que cela est apparu quelque temps en 5.3

Voici mon scénario: J'ai un tableau de vérification des e-mails et je veux m'assurer qu'un code machine et un code d'activation transmis existent sur la même ligne.

Assurez-vous d'inclure use Illuminate\Validation\Rule;

$activationCode = $request->activation_code;                                   

$rules = [                                                                     
    'mc' => [                                                                  
        'required',                                                            
        Rule::exists('email_verifications', 'machineCode')                     
        ->where(function ($query) use ($activationCode) {                      
            $query->where('activationCode', $activationCode);                  
        }),                                                                    
    ],                                                                         
    'activation_code' => 'required|integer|min:5',                             
    'operating_system' => 'required|alpha_num|max:45'                          
];

Le premier argument de la méthode exist est la table et le second est le nom de colonne personnalisé que j'utilise pour le champ 'mc'. Je passe la deuxième colonne à vérifier à l'aide du mot clé "use", puis j'utilise ce champ dans une clause where.

C'est très pratique, car je n'ai plus besoin d'une règle de validation personnalisée.

11
roerjo

Comme vos règles sont des propriétés de modèle, vous devez les modifier avant d’exécuter le validateur.

Vous pouvez changer vos règles pour:

public $rules = array(
    'game_id' => 'required|exists:games,id',
    'team1_id' => 'required|exists:teams,id,game_id,{$game_id}',
    'team2_id' => 'required|exists:teams,id,game_id,{$game_id}'
);

et maintenant, vous devrez utiliser loop pour insérer la valeur correcte à la place de la chaîne {$game_id}.

Je peux vous montrer comment je l'ai fait dans mon cas pour la règle d'édition:

public function validate($data, $translation, $editId = null)
{
    $rules = $this->rules;

    $rules = array_intersect_key($rules, $data);

    foreach ($rules as $k => $v) {
        $rules[$k] = str_replace('{,id}',is_null($editId) ? '' : ','.$editId , $v);
    }

    $v = Validator::make($data, $rules, $translation);

    if ($v->fails())
    {
        $this->errors = $v->errors();
        return false;
    }

    return true;
}

Vous pouvez faire la même chose dans votre cas en changeant {$game_id} en $data['game_id'] (dans mon cas, j'ai changé {,id} en ,$editId 

MODIFIER

Bien sûr, si vous n'avez pas défini $rules comme propriété, vous pouvez simplement faire:

$rules = array(
    'game_id' => 'required|exists:games,id',
    'team1_id' => 'required|exists:teams,id,game_id,'.$data['game_id'],
    'team2_id' => 'required|exists:teams,id,game_id,'.$data['game_id']
);

à la place où vous avez votre ensemble de données.

2
Marcin Nabiałek

essayez ceci sa fonctionne pour moi

'email'=>'required|unique:admintable,Email,'.$adminid.',admin_id',
1
user3151197