2013-05-13 21 views
6

Io uso le seguenti regole per la convalida sulla creazione di un nuovo utente:laravel 4 Convalida

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

Quando si aggiorna un utente esistente io uso lo stesso set di regole come sopra indicato ma non voglio un errore di convalida se il l'utente non ha cambiato la sua e-mail.

Attualmente risolvere questo utilizzando il seguente:

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

Ci si sente come una soluzione sporca a me così mi chiedevo se ci sono alternative migliori.

Si noti inoltre che il metodo changed è qualcosa che ho scritto io stesso. Qualcuno sa se lo è un metodo nativo di Laravel 4 per verificare se una proprietà del modello è cambiata?

Grazie!

+0

Hi controllare questa la mia risposta a questa domanda [http://stackoverflow.com/questions/16976207/laravel-4-validation-uniquedatabase-ignore-current][1], spero che questo aiuto. [1]: http://stackoverflow.com/questions/16976207/laravel-4-validation-uniquedatabase-ignore-current – Bradley

risposta

9

La regola di convalida univoca consente di ignorare un dato ID, che nel tuo caso è l'ID del set di dati che si sta aggiornando.

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

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

+5

BTW, ho risolvere questo problema utilizzando un segnaposto ': id:' nel mio regole di convalida e quindi elaborare le regole prima di convalidare: https://github.com/betawax/role-model/blob/master/src/Betawax/RoleModel/RoleModel.php#L86-L101 –

+0

Mi piace l'idea di usare un segnaposto ma non sono davvero convinto dal tuo approccio. Qualche idea sulla mia "seconda" domanda riguardante uno stato di cambiamento? Ho trovato alcuni riferimenti nella fonte di Laravel 3 su un metodo modificato ma non l'ho trovato finora in Laravel 4 –

+0

Nel mio esempio di codice, sostituisco il segnaposto con '$ this-> getKey()' che è disponibile per nuovi * e * set di dati esistenti. Quindi non devi preoccuparti se stai creando un nuovo modello o aggiornando un modello esistente. Basta sostituire il segnaposto su ogni evento di salvataggio. Puoi farlo sovrascrivendo il metodo 'save()' di Eloquent o usando [eventi modello] (http://four.laravel.com/docs/eloquent#model-events). –

1

Vedere la documentazione sul http://four.laravel.com/docs/validation#rule-unique

È possibile escludere gli utenti proprio ID

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

Conosco il parametro exclude ma non vedo un modo valido e non hacker di iniettarlo nel mio set di regole, quindi la domanda. –

+0

Perché consideri questo hackish? – Puzbie

0

gestisco questo genere di cose nella mia funzione di convalida. Il mio array di validatori è configurato come variabile di classe. Ho poi fare qualcosa di simile:

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

Un approccio è quello di creare una funzione di validazione del modello e chiamarlo con il controller passando l'ingresso, lo scenario e l'ID (da ignorare).

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

Poi nel controller:

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

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

Come altri hanno detto, il 3 ° parametro della regola unica specifica un id di ignorare. È possibile aggiungere altri casi, ad esempio "accesso" per riutilizzare la funzione di convalida.

In alternativa, Jeffrey Way allo Tuts Premium has a great series of lessons in "What's New In Laravel 4" che include un paio di altri approcci per gestire la convalida utilizzando servizi e ascoltatori.

+0

aggiungendo le regole di convalida al modello sembra essere la soluzione giusta. imho è sporco aggiungere il parametro per lo store o l'aggiornamento ogni volta. questo post segue una soluzione simile http://forums.laravel.io/viewtopic.php?id=12104 forse questo aiuta qualcuno. – simon

1

A partire dal 2014/01/14, è possibile utilizzare l'attributo sometimes, credo Taylor li ha aggiunto 2 giorni fa per laravel 4,1

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

sometimes solo convalidare l'input se esiste. questo potrebbe non essere adatto al tuo scenario esatto, se non hai un valore predefinito per l'inserimento.

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

+0

grazie per aver condiviso questo !! – simon

0

Ho risolto questo avendo regole diverse per l'aggiornamento e creare su modelli che hanno bisogno di farlo, come gli utenti.

ho una classe di modello che si estende Eloquente, in cui definisco la convalida, e quindi tutti i modelli figlio che estendere il modello può avere avere entrambi i $ regole e $ update_rules definiti. Se definisci solo $ regole, sarà usato sia per creare che per aggiornare.

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