Ma technique de formulaire qui servira à la fois pour créer un nouvel enregistrement ou pour modifier un enregistrement.
Dans cette exemple, on gère des taches à faire.
J’utilise le bootstrap twitter ce qui explique les noms de class utilisées dans le code HTML.
Classique modèle eloquent
<?php class Todo extends Eloquent{ }
J’ai pris l’habitude de gérer mes routes dans le controller
Route::controller('todo','TodoController');
Une méthode get qui affichera le formulaire et une méthode post pour traiter les résultats. On passe l’id en paramètre.
Comme j’utilise la méthode controller pour les routes, la méthode getTodoEdit sera appelé via l’url todo/todo-edit
Si on ne spécifie pas d’id dans l’url, on créer une nouvelle tache, sinon on modifiera la tache #9 avec l’url /todo/todo-edit/9
<?php class TodoController extends BaseController { public function getTodoEdit($id=null){ if(is_null($id)){ //id null donc création $todo = new Todo; // On récupère la structure de la table Todo }else{ //si id spécifié, ce sera une modification $todo = Todo::find($id); // On récupère les données de la tache //si l'id n'existe pas, on redirige sur la page avec un message d'erreur if(is_null($todo)) return Redirect::to('accueil')->with('flash_error',"L'id $id n'existe pas"); } // On crée des listes pour simplifier la saisie $etiquettes = Todo::select('etiquette')->groupBy('etiquette')->orderBy('etiquette')->get(); $types = Todo::select('type')->groupBy('type')->orderBy('type')->get(); $etats = Todo::withTrashed()->select('etat')->groupBy('etat')->orderBy('etat')->get(); // On stocke dans une variable de session d'ou on vient (utile si on utilise des filtres) Session::put('redirect',URL::previous()); // On crée la vue contenant notre formulaire return View::make('todoEdit') ->with('todo',$todo) ->with('etiquettes',$etiquettes) ->with('types',$types) ->with('etats',$etats) ; } public function postTodoEdit($id=null){ // On passe par l'étape validation avant toute création/modification $rules = array( // On définit les règles 'description' => 'required|min:5', 'etiquette' => 'required', 'type' => 'required', 'etat' => 'required' ); // On personnalise les messages d'erreur si on veut $messages = array( 'description.required' => "La description est obligatoire", 'description.min' => "La description doit faire au moins 5 caractères", 'etiquette.required' =>"L'étiquette est obligatoire", 'type.required' => "Le type est obligatoire", 'etat.required' => "L'état est obligatoire" ); $v = Validator::make(Input::all(), $rules, $messages); // Si la validation passe, on commence le traitement if($v->passes()){ if(is_null($id)){ // id null donc création $todo = new Todo; }else{ // si id spécifié, on récupère l'enregistrement pour le mettre à jour $todo = Todo::findOrFail($id); // si l'id n'existe pas dans la table, on revoie un erreur } $todo->description = Input::get('description'); // On prépare la mise à jour les champs de la table $todo->etiquette = Input::get('etiquette'); $todo->type = Input::get('type'); $todo->etat = Input::get('etat'); $todo->save(); // On sauvegarde les modifications dans la table // On redirige vers la page où on était avant d'arriver sur le formulaire. par défaut sur **/todo** return Redirect::to(Session::get('redirect',url('todo')))->with('flash_success','Enregistrement effectué !');; // Si la validation échoue }else{ // On redirige sur le formulaire avec les erreurs et les valeurs des champs déjà entrés return Redirect::back()->withErrors($v)->withInput(); } } }
Ouvrir et fermer le formulaire. Par défaut il renvoie en POST et utilisera l’url courante.
Dans notre cas, il est impératif d’utiliser l’url courante car elle contient ou pas un id qui déterminera si on ajoute ou si on modifie un enregistrement.
{{Form::open(array('class'=>'form-horizontal'))}} {{Form::close()}}
Un ensemble label + input text
<div class="form-group{{ $errors->has('etiquette') ? ' has-error' : '' }}"> {{Form::label('etiquette','Etiquette', array('class'=>'col-sm-4 control-label'))}} <div class="col-sm-8"> {{Form::text('etiquette',$todo->etiquette,array('class'=>'form-control'))}} </div> <span class="help-block">{{ $errors->has('etiquette') ? $errors->first('etiquette') : '' }}</span> </div>
Un ensemble label + input text + liste de pré-saisie
<div class="form-group{{ $errors->has('etiquette') ? ' has-error' : '' }}"> {{Form::label('etiquette','Etiquette', array('class'=>'col-sm-4 control-label'))}} <div class="col-sm-8"> {{Form::text('etiquette',$todo->etiquette,array('class'=>'form-control', 'style'=>'width:auto;display:inline;'))}} <select class="form-control" style="display:inline; width:20px;" onChange="$('input[name=etiquette]').val($(this).val())"> <option value="">-- Vide --</option> @foreach ($etiquettes as $etiquette) @if(!empty($etiquette->etiquette)) <option value="{{$etiquette->etiquette}}"{{($etiquette->etiquette==$todo->etiquette?' selected':'')}}>{{ucfirst($etiquette->etiquette)}}</option> @endif @endforeach </select> </div> <span class="help-block">{{ $errors->has('etiquette') ? $errors->first('etiquette') : '' }}</span> </div>
Il est important d’utiliser la class Form pour construire les input text car lorsque la validation n’est pas bonne et que l’on revient sur le formulaire, la valeur rentrée a posteriori sera automatiquement renseigné.
Les erreurs renvoyés par →withErrors() se récupère dans la vue via l’objet $errors
Pour afficher un message d’info, on peut ajouter ce code dans la vue.
@if (Session::has('flash_success')) <div class="alert alert-info"> {{Session::get('flash_success')}} </div> @endif
Le code de validation pour un code postal
'code_postal' => array('required','regex:#^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$#')