Tutoriel pour apprendre à créer une application Laravel

Les utilisateurs

Maurice Chavelli

L'administrateur de l'application peut gérer les utilisateurs :

- consulter les paramètres ;

- modifier les paramètres (en particulier « Vu ») ;

- créer un utilisateur ;

- renommer les rôles ;

- supprimer un utilisateur.

Ce tutoriel est destiné à décrire comment tout cela est géré dans l'application.

Commentez

- Titre : Tutoriel pour apprendre à créer une application Laravel

- Auteur : Maurice Chavelli

- Parution : 21 décembre 2017

- Licence : Copyright ® 2017 Laravel. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Le panneau

- III. Marquer « Vu »

- IV. Voir une fiche

- V. Créer un utilisateur

- VI. Modifier un utilisateur

- VII. Supprimer un utilisateur

- VIII. Noms des rôles

- IX. Remerciements

I - Introduction

L'administrateur dispose d'un bloc sur son tableau de bord pour les utilisateurs :

Nous avons déjà vu le code pour les articles et les messages, je n'insiste donc pas.

L'administrateur dispose également d'un menu latéral pour les utilisateurs :

II - Le panneau

Le panneau des utilisateurs apparaît ainsi :

C'est la méthode index du contrôleur UserController qui l'affiche :

1. /**

2. * Display a listing of the resource.

3. *

4. * @return Response

5. */

6. public function index()

7. {

8. return $this->indexSort('total');

9. }

On voit qu'il est fait appel à une autre fonction du contrôleur :

1. /**

2. * Display a listing of the resource.

3. *

4. * @param  string  $role

5. * @return Response

6. */

7. public function indexSort($role)

8. {

9. $counts = $this->user_gestion->counts();

10. $users = $this->user_gestion->index(4, $role);

11. $links = $users->setPath('')->render();

12. $roles = $this->role_gestion->all();

14. return view('back.users.index', compact('users', 'links', 'counts', 'roles'));

15. }

Cette méthode est utilisée pour l'affichage en filtrant le rôle. Dans notre cas le fait de passer « total » revient à afficher tous les utilisateurs. Pour filtrer les rôles, on a ce panneau de boutons qui conduit directement à la fonction vue ci-dessus :

On peut sélectionner par exemple seulement les rédacteurs :

C'est la méthode index du repository UserRepository qui assure la gestion des données :

1. /**

2. * Get users collection.

3. *

4. * @param  int  $n

5. * @param  string  $role

6. * @return Illuminate\Support\Collection

7. */

8. public function index($n, $role)

9. {

10. if($role != 'total')

11. {

12. return $this->model

13. ->with('role')

14. ->whereHas('role', function($q) use($role) {

15. $q->whereSlug($role);

16. })

17. ->oldest('seen')

18. ->latest()

19. ->paginate($n);

20. }

22. return $this->model

23. ->with('role')

24. ->oldest('seen')

25. ->latest()

26. ->paginate($n);

27. }

C'est cette vue qui est utilisée :

La partie du code qui gère le tableau est celle-ci :

1. <div class="table-responsive">

2. <table class="table">

3. <thead>

4. <tr>

5. <th>{{ trans('back/users.name') }}</th>

6. <th>{{ trans('back/users.role') }}</th>

7. <th>{{ trans('back/users.seen') }}</th>

8. <th></th>

9. <th></th>

10. </tr>

11. </thead>

12. <tbody>

13. @include('back.users.table')

14. </tbody>

15. </table>

16. </div>

On voit qu'on inclut une autre vue (back/users/table.blade.php) :

1. @foreach ($users as $user)

2. <tr {!! !$user->seen? 'class="warning"' : '' !!}>

3. <td class="text-primary"><strong>{{ $user->username }}</strong></td>

4. <td>{{ $user->role->title }}</td>

5. <td>{!! Form::checkbox('seen', $user->id, $user->seen) !!}</td>

6. <td>{!! link_to_route('user.show', trans('back/users.see'), [$user->id], ['class' => 'btn btn-success btn-block btn']) !!}</td>

7. <td>{!! link_to_route('user.edit', trans('back/users.edit'), [$user->id], ['class' => 'btn btn-warning btn-block']) !!}</td>

8. <td>

9. {!! Form::open(['method' => 'DELETE', 'route' => ['user.destroy', $user->id]]) !!}

10. {!! Form::destroy(trans('back/users.destroy'), trans('back/users.destroy-warning')) !!}

11. {!! Form::close() !!}

12. </td>

13. </tr>

14. @endforeach

III - Marquer « Vu »

Lorsqu'un utilisateur est nouvellement inscrit, il apparaît comme non vu sur le panneau, avec la case décochée et le fond jauni pour attirer le regard :

Cette action est gérée en JavaScript côté client avec envoi de la requête en Ajax :

1. // Seen gestion

2. $(document).on('change', ':checkbox', function() {

3. $(this).parents('tr').toggleClass('warning');

4. $(this).hide().parent().append('<i class="fa fa-refresh fa-spin"></i>');

5. var token = $('input[name="_token"]').val();

6. $.ajax({

7. url: '{!! url('userseen') !!}' + '/' + this.value,

8. type: 'PUT',

9. data: "seen=" + this.checked + "&_token=" + token

10. })

11. .done(function() {

12. $('.fa-spin').remove();

13. $('input[type="checkbox"]:hidden').show();

14. })

15. .fail(function() {

16. $('.fa-spin').remove();

17. var chk = $('input[type="checkbox"]:hidden');

18. chk.show().prop('checked', chk.is(':checked') ? null:'checked').parents('tr').toggleClass('warning');

19. alert('{{ trans('back/users.fail') }}');

20. });

21. });

Avec une petite animation d'attente :

C'est la méthode updateSeen du contrôleur UserController qui est chargée de la requête :

1. /**

2. * Update the specified resource in storage.

3. *

4. * @param  Illuminate\Http\Request $request

5. * @param  App\Models\User $user

6. * @return Response

7. */

8. public function updateSeen(

9. Request $request,

10. $user)

11. {

12. $this->user_gestion->update($request->all(), $user);

14. return response()->json();

15. }

Il est fait appel à la méthode update du repository UserRepository :

1. /**

2. * Update a user.

3. *

4. * @param  array  $inputs

5. * @param  App\Models\User $user

6. * @return void

7. */

8. public function update($inputs, $user)

9. {

10. $user->confirmed = isset($inputs['confirmed']);

12. $this->save($user, $inputs);

13. }

Ce sera la même méthode pour modifier d'autres champs.

Notez qu'il est fait appel à la liaison du modèle au niveau des routes (route model binding). Regardez dans le service provider app/Providers/RouteServiceProvider :

1. /**

2. * Define your route model bindings, pattern filters, etc.

3. *

4. * @param  \Illuminate\Routing\Router  $router

5. * @return void

6. */

7. public function boot(Router $router)

8. {

9. parent::boot($router);

11. $router->model('user', 'App\Models\User');

12. }

Chaque fois qu'on utilise « user » comme paramètre de route Laravel crée automatiquement le modèle correspondant. C'est pour ça qu'on a directement le modèle comme paramètre dans la fonction updateSeen vue ci-dessus. Ça sera la même chose pour d'autres fonctions que nous allons voir plus loin.

Le contrôleur renvoie une réponse JSON et le JavaScript agit en conséquence.

IV - Voir une fiche

Pour consulter les informations d'un utilisateur, l'administrateur clique sur ce bouton :

C'est la méthode show du contrôleur UserController qui est chargée de la requête :

1. /**

2. * Display the specified resource.

3. *

4. * @param  App\Models\User

5. * @return Response

6. */

7. public function show(User $user)

8. {

9. return view('back.users.show',  compact('user'));

10. }

Le contrôleur génère la vue :

Avec ce code :

1. @extends('back.template')

3. @section('main')

5. @include('back.partials.entete', ['title' => trans('back/users.dashboard'), 'icone' => 'user', 'fil' => link_to('user', trans('back/users.Users')) . ' / ' . trans('back/users.card')])

7. <p>{{ trans('back/users.name') . ' : ' .  $user->username }}</p>

8. <p>{{ trans('back/users.email') . ' : ' .  $user->email }}</p>

9. <p>{{ trans('back/users.role') . ' : ' .  $user->role->title }}</p>

11. @stop

Avec ce rendu :

V - Créer un utilisateur

L'administrateur peut créer un utilisateur en cliquant sur ce bouton :

C'est la méthode create du contrôleur UserController qui est chargée de la requête :

1. /**

2. * Show the form for creating a new resource.

3. *

4. * @return Response

5. */

6. public function create()

7. {

8. return view('back.users.create', $this->role_gestion->getAllSelect());

9. }

Il est fait appel à la méthode getAllSelect du repository RoleRepository :

1. /**

2. * Get roles collection.

3. *

4. * @param  App\Models\User

5. * @return Array

6. */

7. public function getAllSelect()

8. {

9. $select = $this->all()->lists('title', 'id');

11. return compact('select');

12. }

En effet, on a besoin de la liste des rôles pour le formulaire.

Le contrôleur génère la vue :

Avec ce code :

1. @extends('back.template')

3. @section('main')

5. <!-- Entête de page -->

6. @include('back.partials.entete', ['title' => trans('back/users.dashboard'), 'icone' => 'user', 'fil' => link_to('user', trans('back/users.Users')) . ' / ' . trans('back/users.creation')])

8. <div class="col-sm-12">

9. {!! Form::open(['url' => 'user', 'method' => 'post', 'class' => 'form-horizontal panel']) !!}

10. {!! Form::control('text', 0, 'username', $errors, trans('back/users.name')) !!}

11. {!! Form::control('email', 0, 'email', $errors, trans('back/users.email')) !!}

12. {!! Form::control('password', 0, 'password', $errors, trans('back/users.password')) !!}

13. {!! Form::control('password', 0, 'password_confirmation', $errors, trans('back/users.confirm-password')) !!}

14. {!! Form::selection('role', $select, null, trans('back/users.role')) !!}

15. {!! Form::submit(trans('front/form.send')) !!}

16. {!! Form::close() !!}

17. </div>

19. @stop

Ce qui donne ce formulaire :

La méthode store du contrôleur UserController est chargée de gérer la soumission :

1. /**

2. * Store a newly created resource in storage.

3. *

4. * @param  App\requests\UserCreateRequest $request

5. *

6. * @return Response

7. */

8. public function store(

9. UserCreateRequest $request)

10. {

11. $this->user_gestion->store($request->all());

13. return redirect('user')->with('ok', trans('back/users.created'));

14. }

La validation est assurée par la requête de formulaire UserCreateRequest :

1. <?php namespace App\Http\Requests;

3. class UserCreateRequest extends Request {

5. /**

6. * Get the validation rules that apply to the request.

7. *

8. * @return array

9. */

10. public function rules()

11. {

12. return [

13. 'username' => 'required|max:30|alpha|unique:users',

14. 'email' => 'required|email|unique:users',

15. 'password' => 'required|confirmed|min:8'

16. ];

17. }

19. }

Si la validation se passe bien le contrôleur appelle la méthode store du repository UserRepository pour la mise à jour dans la base :

1. /**

2. * Create a user.

3. *

4. * @param  array  $inputs

5. * @param  int    $confirmation_code

6. * @return App\Models\User

7. */

8. public function store($inputs, $confirmation_code = null)

9. {

10. $user = new $this->model;

12. $user->password = bcrypt($inputs['password']);

14. if($confirmation_code) {

15. $user->confirmation_code = $confirmation_code;

16. } else {

17. $user->confirmed = true;

18. }

20. $this->save($user, $inputs);

22. return $user;

23. }

Puis le contrôleur affiche à nouveau la liste avec un message :

Sinon on reçoit les messages d'erreur correspondants :

VI - Modifier un utilisateur

L'administrateur peut modifier les informations d'un utilisateur en cliquant sur ce bouton :

C'est la méthode edit du contrôleur UserController qui est chargée de la requête :

1. /**

2. * Show the form for editing the specified resource.

3. *

4. * @param  App\Models\User

5. * @return Response

6. */

7. public function edit(User $user)

8. {

9. return view('back.users.edit', array_merge(compact('user'), $this->role_gestion->getAllSelect()));

10. }

Le contrôleur génère la vue :

Avec ce code :

1. @extends('back.template')

3. @section('main')

5. <!-- Entête de page -->

6. @include('back.partials.entete', ['title' => trans('back/users.dashboard'), 'icone' => 'user', 'fil' => link_to('user', trans('back/users.Users')) . ' / ' . trans('back/users.edition')])

8. <div class="col-sm-12">

9. {!! Form::model($user, ['route' => ['user.update', $user->id], 'method' => 'put', 'class' => 'form-horizontal panel']) !!}

10. {!! Form::control('text', 0, 'username', $errors, trans('back/users.name')) !!}

11. {!! Form::control('email', 0, 'email', $errors, trans('back/users.email')) !!}

12. {!! Form::selection('role', $select, $user->role_id, trans('back/users.role')) !!}

13. {!! Form::submit(trans('front/form.send')) !!}

14. {!! Form::close() !!}

15. </div>

17. @stop

Avec ce rendu :

Le même formulaire que celui de la création, mais sans le mot de passe et avec une case à cocher pour la confirmation.

La méthode update du contrôleur UserController est chargée de gérer la soumission :

1. /**

2. * Update the specified resource in storage.

3. *

4. * @param  App\requests\UserUpdateRequest $request

5. * @param  App\Models\User

6. * @return Response

7. */

8. public function update(

9. UserUpdateRequest $request,

10. $user)

11. {

12. $this->user_gestion->update($request->all(), $user);

14. return redirect('user')->with('ok', trans('back/users.updated'));

15. }

La validation est assurée par la requête de formulaire UserUpdateRequest :

1. <?php namespace App\Http\Requests;

3. class UserUpdateRequest extends Request {

5. /**

6. * Get the validation rules that apply to the request.

7. *

8. * @return array

9. */

10. public function rules()

11. {

12. $id = $this->user->id;

13. return $rules = [

14. 'username' => 'required|max:30|alpha|unique:users,username,' . $id,

15. 'email' => 'required|email|unique:users,email,' . $id

16. ];

17. }

19. }

Très proche de celle de la création, mais sans le mot de passe et aussi en récupérant l'identifiant de l'utilisateur dans la requête pour la règle d'unicité du nom.

Si la validation se passe bien le contrôleur appelle la méthode update du repository UserRepository pour la mise à jour dans la base :

1. /**

2. * Update a user.

3. *

4. * @param  array  $inputs

5. * @param  App\Models\User $user

6. * @return void

7. */

8. public function update($inputs, $user)

9. {

10. $user->confirmed = isset($inputs['confirmed']);

12. $this->save($user, $inputs);

13. }

Puis le contrôleur affiche à nouveau la liste avec un message :

Sinon on renvoie et on affiche les messages d'erreur de saisie.

VII - Supprimer un utilisateur

L'administrateur peut modifier les informations d'un utilisateur en cliquant sur ce bouton :

C'est la méthode destroy du contrôleur UserController qui est chargée de la requête :

1. /**

2. * Remove the specified resource from storage.

3. *

4. * @param  App\Models\user $user

5. * @return Response

6. */

7. public function destroy(User $user)

8. {

9. $this->user_gestion->destroyUser($user);

11. return redirect('user')->with('ok', trans('back/users.destroyed'));

12. }

Côté client on affiche quand même un petit message en JavaScript par sécurité :

Il est fait appel à la méthode destroyUser du repository UserRepository :

1. /**

2. * Destroy a user.

3. *

4. * @param  App\Models\User $user

5. * @return void

6. */

7. public function destroyUser(User $user)

8. {

9. $user->comments()->delete();

11. $user->delete();

12. }

On commence par supprimer les commentaires éventuels de l'utilisateur et ensuite on le supprime.

On affiche un message de confirmation pour l'administrateur :

VIII - Noms des rôles

Si l'administrateur veut modifier le nom des rôles, il doit passer par le menu latéral :

C'est la méthode getRoles du contrôleur UserController qui est chargée de la requête :

1. /**

2. * Display the roles form

3. *

4. * @return Response

5. */

6. public function getRoles()

7. {

8. $roles = $this->role_gestion->all();

10. return view('back.users.roles', compact('roles'));

11. }

Il est fait appel à la méthode all du repository RoleRepository :

1. /**

2. * Get all roles.

3. *

4. * @return Illuminate\Support\Collection

5. */

6. public function all()

7. {

8. return $this->role->all();

9. }

On récupère toutes les informations des rôles.

Le contrôleur génère la vue :

Avec ce code :

1. @extends('back.template')

3. @section('main')

5. @include('back.partials.entete', ['title' => trans('back/roles.dashboard'), 'icone' => 'user', 'fil' => link_to('user', trans('back/users.Users')) . ' / ' . trans('back/roles.roles')])

7. <div class="col-sm-12">

8. @if(session()->has('ok'))

9. @include('partials/error', ['type' => 'success', 'message' => session('ok')])

10. @endif

11. {!! Form::open(['url' => 'user/roles', 'method' => 'post', 'class' => 'form-horizontal panel']) !!}

12. @foreach ($roles as $role)

13. {!! Form::control('text', 0, $role->slug, $errors, trans('back/roles.' . $role->slug), $role->title) !!}

14. @endforeach

15. {!! Form::submit(trans('front/form.send')) !!}

16. {!! Form::close() !!}

17. </div>

19. @stop

Et ce rendu :

On peut donc ici changer les noms.

La méthode postRoles du contrôleur UserController est chargée de gérer la soumission :

1. /**

2. * Update roles

3. *

4. * @param  App\requests\RoleRequest $request

5. * @return Response

6. */

7. public function postRoles(RoleRequest $request)

8. {

9. $this->role_gestion->update($request->except('_token'));

11. return redirect('user/roles')->with('ok', trans('back/roles.ok'));

12. }

La validation est assurée par la requête de formulaire RoleRequest :

1. <?php namespace App\Http\Requests;

3. class RoleRequest extends Request {

5. /**

6. * Get the validation rules that apply to the request.

7. *

8. * @return array

9. */

10. public function rules()

11. {

12. return [

13. 'admin' => 'required|alpha|max:50',

14. 'redac' => 'required|alpha|max:50',

15. 'user'  => 'required|alpha|max:50'

16. ];

17. }

19. }

Si la validation se passe bien, le contrôleur fait appel à la méthode update du repository RoleRepository :

1. /**

2. * Update roles.

3. *

4. * @param  array  $inputs

5. * @return void

6. */

7. public function update($inputs)

8. {

9. foreach ($inputs as $key => $value)

10. {

11. $role = $this->role->where('slug', $key)->firstOrFail();

12. $role->title = $value;

13. $role->save();

14. }

15. }

On parcourt tous les rôles pour les mettre à jour.

Le contrôleur régénère la vue en la complétant avec un message :

On a ainsi fait le tour de la gestion des utilisateurs et de leurs rôles.

IX - Remerciements

Nous remercions Maurice Chavelli qui nous autorise à publier ce tutoriel.

Nous tenons également à remercier Winjerome pour la mise au gabarit et Claude Leloup pour la relecture.