wake-up-neo.net

Laravel Validierung: existiert mit zusätzlicher Spaltenbedingung - benutzerdefinierte Validierungsregel

Gibt es eine Möglichkeit, auf ein anderes Feld zu verweisen, wenn Sie die vorhandene Validierungsregel in Laravel angeben? Ich möchte sagen können, dass Eingabe a in Tabelle a vorhanden sein muss, Eingabe b muss in Tabelle b vorhanden sein UND der Wert für Spalte x in Tabelle b muss dem Eingang a entsprechen.

Am besten durch Beispiel erklärt:

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

Mit meinen Validierungsregeln möchte ich also Folgendes sicherstellen können:

  • game_id existiert in der games-Tabelle (id-Feld)
  • team1_id ist in der Tabelle teams (Feld id) vorhanden, und die Spalte game_id (in der Tabelle teams) muss mit dem Wert der Eingabe game_id übereinstimmen.
  • Wie oben für team2_id

Wenn ich also in meinem Formular 1 für game_id eingegeben habe, möchte ich sicherstellen können, dass der Datensatz in der teams-Tabelle für team1_id und team2_id den Wert 1 für game_id hat.

Ich hoffe das macht Sinn.

Vielen Dank

10
Jonathon

Sie möchten eine benutzerdefinierte Validierungsregel , und ich würde dafür eine eigene Klasse erstellen. Der Einfachheit halber ist hier jedoch das Gleiche beim Inline-Verschluss der Fall:

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

Dann benutze einfach folgendes:

$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

BEARBEITEN: Vermutlich funktioniert das in Laravel 5.5 nicht. @ user3151197 Antwort könnte den Trick tun.

Ich verwende Laravel 5.4 und kann die benutzerdefinierte Regel zu den existierenden und eindeutigen Regeln hinzufügen. Ich denke, das ist irgendwann in 5.3 entstanden

Hier ist mein Szenario: Ich habe eine E-Mail-Überprüfungstabelle und möchte sicherstellen, dass ein übergebener Maschinencode und Aktivierungscode in derselben Zeile vorhanden sind.

Stellen Sie sicher, dass Sie use Illuminate\Validation\Rule; angeben.

$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'                          
];

Das erste Argument in der vorhandenen Methode ist die Tabelle und das zweite ist der Name der benutzerdefinierten Spalte, den ich für das Feld 'mc' verwende. Ich übergebe die zweite Spalte, die ich überprüfen möchte, mit dem Schlüsselwort 'use' und verwende dieses Feld dann in einer where-Klausel.

Dies ist sehr praktisch, da ich jetzt keine benutzerdefinierte Validierungsregel mehr benötige.

11
roerjo

Da es sich bei Ihren Regeln um eine Modelleigenschaft handelt, müssen Sie einige Änderungen vornehmen, bevor Sie den Validator ausführen.

Sie können Ihre Regeln ändern in:

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

und jetzt müssen Sie eine Schleife verwenden, um den korrekten Wert anstelle von {$game_id} string einzufügen.

Ich kann Ihnen zeigen, wie ich es in meinem Fall für die Bearbeitungsregel gemacht habe:

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

Sie können dasselbe in Ihrem Fall tun, indem Sie {$game_id} in $data['game_id'] ändern (in meinem Fall habe ich {,id} in ,$editId geändert. 

EDIT

Wenn Sie $rules nicht als Eigenschaft festgelegt haben, können Sie dies einfach tun:

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

dort, wo Sie Ihre Daten haben.

2

probieren Sie es aus, es funktioniert für mich

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