2013-05-13 3 views
6

J'utilise les règles suivantes pour la validation sur la création d'un nouvel utilisateur:Laravel 4 Validation

protected $rules= [ 
    'name' => 'required', 
    'email' => [ 
     'required', 
     'unique:user', 
     'email' 
    ] 
]; 

Lorsque la mise à jour d'un utilisateur existant J'utilise le même ensemble de règles comme indiqué ci-dessus mais ne veulent pas d'une erreur de validation si la l'utilisateur n'a pas changé d'adresse du tout.

Je résous actuellement cela en utilisant les éléments suivants:

if (!User::changed('email')) { 
    unset($user->email); 
} 

Il se sent comme une solution sale pour moi, je me demandais si s'il existe de meilleures alternatives.

Notez également que la méthode changed est quelque chose que j'ai écrit moi-même. Est-ce que quelqu'un sait si est une méthode native Laravel 4 pour vérifier si une propriété du modèle a changé?

Merci!

+0

Salut Cochez cette ma réponse à cette question [http://stackoverflow.com/questions/16976207/laravel-4-validation-uniquedatabase-ignore-current][1], j'espère que cette aide. [1]: http://stackoverflow.com/questions/16976207/laravel-4-validation-uniquedatabase-ignore-current – Bradley

Répondre

9

La règle de validation unique permet d'ignorer un ID donné, qui dans votre cas est l'ID du fichier que vous mettez à jour.

'email' => 'unique:users,email_address,10' 

http://four.laravel.com/docs/validation#rule-unique

+5

BTW, je résoudre ce problème en utilisant un espace réservé ': id:' dans mon règles de validation, puis traiter les règles avant de valider: https://github.com/betawax/role-model/blob/master/src/Betawax/RoleModel/RoleModel.php#L86-L101 –

+0

J'aime l'idée d'utiliser un espace réservé mais je ne suis pas vraiment convaincu par votre approche. Des pensées sur ma «deuxième» question concernant un changement d'état? J'ai trouvé quelques références dans la source de Laravel 3 sur une méthode modifiée mais je ne l'ai pas trouvée jusqu'ici dans Laravel 4 –

+0

Dans mon exemple de code, je remplace l'espace réservé par '$ this-> getKey()' qui est disponible pour new * et * ensembles de données existants. Vous n'avez donc pas à vous soucier de savoir si vous créez un nouveau modèle ou si vous mettez à jour un modèle existant. Remplacez simplement l'espace réservé à chaque événement de sauvegarde. Vous pouvez le faire en écrasant la méthode 'save()' d'Eloquent ou en utilisant [événements de modèle] (http://four.laravel.com/docs/eloquent#model-events). –

1

Voir la documentation sur http://four.laravel.com/docs/validation#rule-unique

Vous pouvez exclure les utilisateurs propres id

protected $rules= [ 
    'name' => 'required', 
    'email' => [ 
     'required', 
     'unique:user,email,THE_USERS_USER_ID', 
     'email' 
    ] 
]; 
+1

Je connais le paramètre exclude mais je ne vois pas de manière non-hackish valide de l'injecter dans mon ruleset d'où la question. –

+0

Pourquoi considérez-vous ce hackish? – Puzbie

0

Je gère ce genre de chose dans ma fonction validateur. Mon tableau de validateurs est configuré en tant que variable de classe. Je fais alors quelque chose comme ceci:

public function validate() 
{ 
    //exclude the current user id from 'unqiue' validators 
    if($this->id > 0) 
    { 
     $usernameUnique = 'unique:users,username,'.$this->id; 
     $emailUnique = 'unique:users,email,'.$this->id; 
     $apiUnique = 'unique:users,api_key,'.$this->id; 
    } 
    else 
    { 
     $usernameUnique = 'unique:users,username'; 
     $emailUnique = 'unique:users,email'; 
     $apiUnique = 'unique:users,api_key'; 
    } 

    $this->validators['username'] = array('required', 'max:32', $usernameUnique); 
    $this->validators['email'] = array('required', 'max:32', $emailUnique); 
    $this->validators['api_key'] = array('required', 'max:32', $apiUnique); 

    $val = Validator::make($this->attributes, $this->validators); 

    if ($val->fails()) 
    { 
     throw new ValidationException($val); 
    } 
} 
4

Une approche consiste à créer une fonction de validation dans le modèle et l'appeler avec le contrôleur en passant l'entrée, scénario et id (à ignorer).

public function validate($input, $scenario, $id = null) 
{ 
    $rules = []; 

    switch($scenario) 
    { 
     case 'store': 
      $rules = [ 
       'name'  => 'required|min:5|unique:users', 
       'email' => 'required|email|unique:users', 
       'password' => 'required|min:4|confirmed' 
      ]; 
      break; 

     case 'update'; 
      $rules = [ 
       'name'  => 'required|min:5|unique:users' .',name,' . $id, 
       'email' => 'required|email|unique:users' .',email,' . $id, 
       'password' => 'min:4|confirmed' 
      ]; 
      break; 
    } 

    return Validator::make($input, $rules); 
} 

Ensuite, dans le contrôleur:

$input  = Input::all(); 
    $validation = $user->validate($input, 'update', $user->id); 

    if ($validation->fails()) 
    { 
     // Do stuff 
    } 
    else 
    { 
     // Validation passes 
     // Do other stuff 
    } 

Comme d'autres ont mentionné, le 3ème paramètre de la règle unique, spécifie un identifiant à ignorer. Vous pouvez ajouter d'autres cas, tels que 'login' pour réutiliser la fonction de validation.

Sinon, Jeffrey Way au Tuts Premium has a great series of lessons in "What's New In Laravel 4" qui comprend quelques autres approches pour gérer la validation en utilisant les services et les écouteurs.

+0

ajoutant les règles de validation au modèle semble être la bonne solution. A mon avis, il est sale d'ajouter le paramètre pour stocker ou mettre à jour à chaque fois. ce post suit une solution similaire http://forums.laravel.io/viewtopic.php?id=12104 peut-être que cela aide quelqu'un. – simon

1

Au 14/01/2014, vous pouvez utiliser sometimes attribut, je crois que Taylor a ajouté il y a les 2 jours Laravel 4,1

$v = Validator::make($data, array(
    'email' => 'sometimes|required|email', 
)); 

sometimes ne valider l'entrée si elle existe. Cela peut ou non convenir à votre scénario exact, si vous n'avez pas de valeur par défaut pour insérer.

http://laravel.com/docs/validation#conditionally-adding-rules

+0

merci de partager cela !! – simon

0

J'ai résolu ce problème en ayant des règles différentes pour la mise à jour et de créer des modèles qui ont besoin de le faire, comme les utilisateurs.

J'ai une classe de modèle qui s'étend Eloquent, où je la validation définis, puis tous les modèles enfants qui étendons le modèle peut avoir avoir deux règles $ et $ update_rules définis. Si vous définissez seulement $ rules, il sera utilisé à la fois pour créer et mettre à jour.

class Model extends Eloquent { 
    protected $errors; 
    protected static $rules = array();  
    protected $validator; 

    public function __construct(array $attributes = array(), Validator $validator = null) { 
     parent::__construct($attributes);  
     $this->validator = $validator ?: \App::make('validator'); 
    } 

    protected static function boot() { 
     parent::boot(); 

     # call validatie when createing 
     static::creating(function($model) { 
      return $model->validate(); 
     }); 

     # call validatie when updating with $is_update = true param 
     static::updating(function($model) { 
      return $model->validate(true); 
     }); 
    } 

    public function validate($is_update = false) { 
     # if we have $update_rules defined in the child model, and save is an update 
     if ($is_update and isset(static::$update_rules)) { 
      $v = $this->validator->make($this->attributes, static::$update_rules); 
     } 
     else { 
      $v = $this->validator->make($this->attributes, static::$rules); 
     } 

     if ($v->passes()) { 
      return true; 
     } 

     $this->setErrors($v->messages()); 
     return false; 
    } 

    protected function setErrors($errors) { 
     $this->errors = $errors; 
    } 

    public function getErrors() { 
     return $this->errors; 
    } 

    public function hasErrors() { 
     return ! empty($this->errors); 
    } 
}