Ich habe ein Laravel- User
Modell, das eine eindeutige Validierungsregel für username
und hat email
. Wenn ich in meinem Repository das Modell aktualisiere, validiere ich die Felder erneut, um kein Problem mit der erforderlichen Regelüberprüfung zu haben:
public function update($id, $data) {
$user = $this->findById($id);
$user->fill($data);
$this->validate($user->toArray());
$user->save();
return $user;
}
Dies schlägt beim Testen mit fehl
ValidationException: {"username":["The username has already been taken."],"email":["The email has already been taken."]}
Gibt es eine Möglichkeit, dies elegant zu beheben?
php
laravel
validation
eloquent
Tom Macdonald
quelle
quelle
unique:table,column,except,idColumn
unique
, bedeutet, dass ich eslte
als verwendet habe,'order'=> 'lte:products,stock,2'
aber es funktioniert nicht warum?Ein weiterer eleganter Weg ...
Erstellen Sie in Ihrem Modell eine statische Funktion:
public static function rules ($id=0, $merge=[]) { return array_merge( [ 'username' => 'required|min:3|max:12|unique:users,username' . ($id ? ",$id" : ''), 'email' => 'required|email|unique:member'. ($id ? ",id,$id" : ''), 'firstname' => 'required|min:2', 'lastname' => 'required|min:2', ... ], $merge); }
Validierung beim Erstellen:
Validierung beim Update:
Validierung beim Update mit einigen zusätzlichen Regeln:
$extend_rules = [ 'password' => 'required|min:6|same:password_again', 'password_again' => 'required' ]; $validator = Validator::make($input, User::rules($id, $extend_rules));
Nett.
quelle
'email' => 'required|email|unique:member'. ($id ? ",id,$id" : '')
Arbeiten innerhalb meiner Frage:
public function update($id, $data) { $user = $this->findById($id); $user->fill($data); $this->validate($user->toArray(), $id); $user->save(); return $user; } public function validate($data, $id=null) { $rules = User::$rules; if ($id !== null) { $rules['username'] .= ",$id"; $rules['email'] .= ",$id"; } $validation = Validator::make($data, $rules); if ($validation->fails()) { throw new ValidationException($validation); } return true; }
ist das, was ich getan habe, basierend auf der oben akzeptierten Antwort.
BEARBEITEN: Mit Formularanfragen wird alles einfacher:
<?php namespace App\Http\Requests; class UpdateUserRequest extends Request { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'name' => 'required|unique:users,username,'.$this->id, 'email' => 'required|unique:users,email,'.$this->id, ]; } }
Sie müssen nur die UpdateUserRequest an Ihre Aktualisierungsmethode übergeben und die Modell-ID POSTEN.
quelle
Einzigartige Validierung mit unterschiedlicher Spalten-ID in Laravel
'UserEmail'=>"required|email|unique:users,UserEmail,$userID,UserID"
quelle
_id
andere Antworten für mich nicht funktionierten.Laravel 5 kompatibler und generischer Weg:
Ich hatte nur das gleiche Problem und löste es auf generische Weise. Wenn Sie ein Element erstellen, werden die Standardregeln verwendet. Wenn Sie ein Element aktualisieren, werden Ihre Regeln überprüft
:unique
und automatisch ein Ausschluss eingefügt (falls erforderlich).Erstellen Sie eine
BaseModel
Klasse und lassen Sie alle Ihre Modelle davon erben:<?php namespace App; use Illuminate\Database\Eloquent\Model; class BaseModel extends Model { /** * The validation rules for this model * * @var array */ protected static $rules = []; /** * Return model validation rules * * @return array */ public static function getRules() { return static::$rules; } /** * Return model validation rules for an update * Add exception to :unique validations where necessary * That means: enforce unique if a unique field changed. * But relax unique if a unique field did not change * * @return array; */ public function getUpdateRules() { $updateRules = []; foreach(self::getRules() as $field => $rule) { $newRule = []; // Split rule up into parts $ruleParts = explode('|',$rule); // Check each part for unique foreach($ruleParts as $part) { if(strpos($part,'unique:') === 0) { // Check if field was unchanged if ( ! $this->isDirty($field)) { // Field did not change, make exception for this model $part = $part . ',' . $field . ',' . $this->getAttribute($field) . ',' . $field; } } // All other go directly back to the newRule Array $newRule[] = $part; } // Add newRule to updateRules $updateRules[$field] = join('|', $newRule); } return $updateRules; } }
Sie definieren jetzt Ihre Regeln in Ihrem Modell so, wie Sie es gewohnt sind:
protected static $rules = [ 'name' => 'required|alpha|unique:roles', 'displayName' => 'required|alpha_dash', 'permissions' => 'array', ];
Und validieren Sie sie in Ihrem Controller. Wenn das Modell nicht validiert wird, wird es automatisch mit den entsprechenden Validierungsfehlern zum Formular zurückgeleitet. Wenn keine Validierungsfehler aufgetreten sind, wird der Code danach weiter ausgeführt.
public function postCreate(Request $request) { // Validate $this->validate($request, Role::getRules()); // Validation successful -> create role Role::create($request->all()); return redirect()->route('admin.role.index'); } public function postEdit(Request $request, Role $role) { // Validate $this->validate($request, $role->getUpdateRules()); // Validation successful -> update role $role->update($request->input()); return redirect()->route('admin.role.index'); }
Das ist es! :) Beachten Sie, dass wir beim Erstellen
Role::getRules()
und beim Bearbeiten aufrufen$role->getUpdateRules()
.quelle
oder was Sie in Ihrer Formularanforderung tun könnten, ist (für Laravel 5.3+)
public function rules() { return [ 'email' => 'required|email|unique:users,email,'.$this->user, //here user is users/{user} from resource's route url ]; }
Ich habe es in Laravel 5.6 gemacht und es hat funktioniert.
quelle
Ich habe die BaseModel-Klasse, also brauchte ich etwas allgemeineres.
//app/BaseModel.php public function rules() { return $rules = []; } public function isValid($id = '') { $validation = Validator::make($this->attributes, $this->rules($id)); if($validation->passes()) return true; $this->errors = $validation->messages(); return false; }
Nehmen wir in der Benutzerklasse an, ich brauche nur E-Mail und Namen, um validiert zu werden:
//app/User.php //User extends BaseModel public function rules($id = '') { $rules = [ 'name' => 'required|min:3', 'email' => 'required|email|unique:users,email', 'password' => 'required|alpha_num|between:6,12', 'password_confirmation' => 'same:password|required|alpha_num|between:6,12', ]; if(!empty($id)) { $rules['email'].= ",$id"; unset($rules['password']); unset($rules['password_confirmation']); } return $rules; }
Ich habe dies mit phpunit getestet und funktioniert einwandfrei.
//tests/models/UserTest.php public function testUpdateExistingUser() { $user = User::find(1); $result = $user->id; $this->assertEquals(true, $result); $user->name = 'test update'; $user->email = '[email protected]'; $user->save(); $this->assertTrue($user->isValid($user->id), 'Expected to pass'); }
Ich hoffe, dass ich jemandem helfen kann, auch wenn ich eine bessere Idee habe. Danke, dass du auch deine geteilt hast. (getestet auf Laravel 5.0)
quelle
Ein einfaches Beispiel für die Aktualisierung von Rollen
// model/User.php class User extends Eloquent { public static function rolesUpdate($id) { return array( 'username' => 'required|alpha_dash|unique:users,username,' . $id, 'email' => 'required|email|unique:users,email,'. $id, 'password' => 'between:4,11', ); } }
.
// controllers/UsersControllers.php class UsersController extends Controller { public function update($id) { $user = User::find($id); $validation = Validator::make($input, User::rolesUpdate($user->id)); if ($validation->passes()) { $user->update($input); return Redirect::route('admin.user.show', $id); } return Redirect::route('admin.user.edit', $id)->withInput()->withErrors($validation); } }
quelle
Ich rufe verschiedene Validierungsklassen für Store und Update auf. In meinem Fall möchte ich nicht alle Felder aktualisieren, daher habe ich baseRules für allgemeine Felder zum Erstellen und Bearbeiten. Fügen Sie jeweils zusätzliche Validierungsklassen hinzu. Ich hoffe mein Beispiel ist hilfreich. Ich benutze Laravel 4.
Modell:
public static $baseRules = array( 'first_name' => 'required', 'last_name' => 'required', 'description' => 'required', 'description2' => 'required', 'phone' => 'required | numeric', 'video_link' => 'required | url', 'video_title' => 'required | max:87', 'video_description' => 'required', 'sex' => 'in:M,F,B', 'title' => 'required' ); public static function validate($data) { $createRule = static::$baseRules; $createRule['email'] = 'required | email | unique:musicians'; $createRule['band'] = 'required | unique:musicians'; $createRule['style'] = 'required'; $createRule['instrument'] = 'required'; $createRule['myFile'] = 'required | image'; return Validator::make($data, $createRule); } public static function validateUpdate($data, $id) { $updateRule = static::$baseRules; $updateRule['email'] = 'required | email | unique:musicians,email,' . $id; $updateRule['band'] = 'required | unique:musicians,band,' . $id; return Validator::make($data, $updateRule); }
Controller: Speichermethode:
public function store() { $myInput = Input::all(); $validation = Musician::validate($myInput); if($validation->fails()) { $key = "errorMusician"; return Redirect::to('musician/create') ->withErrors($validation, 'musicain') ->withInput(); } }
Aktualisierungsmethode:
public function update($id) { $myInput = Input::all(); $validation = Musician::validateUpdate($myInput, $id); if($validation->fails()) { $key = "error"; $message = $validation->messages(); return Redirect::to('musician/' . $id) ->withErrors($validation, 'musicain') ->withInput(); } }
quelle
public static function custom_validation() { $rules = array('title' => 'required ','description' => 'required','status' => 'required',); $messages = array('title.required' => 'The Title must be required','status.required' => 'The Status must be required','description.required' => 'The Description must be required',); $validation = Validator::make(Input::all(), $rules, $messages); return $validation; }
quelle
Ich hatte das gleiche Problem. Was ich getan habe: Fügen Sie in meiner Ansicht ein verstecktes Feld mit der ID eines Modells hinzu und überprüfen Sie im Validator das eindeutige Feld, nur wenn ich eine ID aus der Ansicht habe.
$this->validate( $request, [ 'index' => implode('|', ['required', $request->input('id') ? '' : 'unique:members']), 'name' => 'required', 'surname' => 'required', ] );
quelle
'email' => [ 'required', Rule::exists('staff')->where(function ($query) { $query->where('account_id', 1); }), ], 'email' => [ 'required', Rule::unique('users')->ignore($user->id)->where(function ($query) { $query->where('account_id', 1); }) ],
quelle
Sie können Code unten versuchen
return [ 'email' => 'required|email|max:255|unique:users,email,' .$this->get('id'), 'username' => 'required|alpha_dash|max:50|unique:users,username,'.$this->get('id'), 'password' => 'required|min:6', 'confirm-password' => 'required|same:password', ];
quelle
Wenn Sie eine andere Spalte haben, die als Fremdschlüssel oder Index verwendet wird, müssen Sie dies auch in der Regel wie dieser angeben.
'phone' => [ "required", "phone", Rule::unique('shops')->ignore($shopId, 'id')->where(function ($query) { $query->where('user_id', Auth::id()); }), ],
quelle
Laravel 5.8 einfach und leicht
Sie können dies alles in einer Formularanfrage mit ganz nett tun. . .
Erstellen Sie zunächst ein Feld, in dem Sie die ID (unsichtbar) in der normalen Bearbeitungsform übergeben können. dh
<div class="form-group d-none"> <input class="form-control" name="id" type="text" value="{{ $example->id }}" > </div>
... Fügen Sie dann die Regelklasse wie folgt zu Ihrer Formularanforderung hinzu:
use Illuminate\Validation\Rule;
... Fügen Sie die eindeutige Regel hinzu und ignorieren Sie die aktuelle ID wie folgt:
public function rules() { return [ 'example_field_1' => ['required', Rule::unique('example_table')->ignore($this->id)], 'example_field_2' => 'required', ];
... Geben Sie abschließend den Hinweis auf die Formularanforderung in die Aktualisierungsmethode genauso ein wie auf die Speichermethode:
public function update(ExampleValidation $request, Examle $example) { $example->example_field_1 = $request->example_field_1; ... $example->save(); $message = "The aircraft was successully updated"; return back()->with('status', $message); }
Auf diese Weise wiederholen Sie den Code nicht unnötig :-)
quelle
public function rules() { if ($this->method() == 'PUT') { $post_id = $this->segment(3); $rules = [ 'post_title' => 'required|unique:posts,post_title,' . $post_id ]; } else { $rules = [ 'post_title' => 'required|unique:posts,post_title' ]; } return $rules; }
quelle
Für eine benutzerdefinierte FormRequest und Laravel 5.7+ können Sie die ID Ihres aktualisierten Modells wie folgt abrufen:
public function rules() { return [ 'name' => 'required|min:5|max:255|unique:schools,name,'.\Request::instance()->id ]; }
quelle
Für alle, die eine Formularanfrage verwenden
In meinem Fall habe ich alle folgenden Versuche unternommen: Keiner von ihnen hat funktioniert:
$this->id
,$this->user->id
,$this->user
.Es war, weil ich weder auf das Modell
$id
noch$id
direkt zugreifen konnte .Also habe ich das
$id
von einer Abfrage erhalten, die dasselbeunique
Feld verwendet, das ich zu validieren versuche:/** * Get the validation rules that apply to the request. * * @return array */ public function rules() { $id = YourModel::where('unique_field',$this->request->get('unique_field'))->value('id'); return [ 'unique_field' => ['rule1','rule2',Rule::unique('yourTable')->ignore($id)], ]; }
quelle