Laravel

Un framework qui rend heureux

Voir cette catégorie
Vers le bas
Créer une application : les utilisateurs
Dimanche 22 mars 2015 17:33

Article mis à jour le 29/10/2015

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
Cet article est destiné à décrire comment tout cela est géré dans l'application. L'administrateur dispose d'un bloc sur son tableau de bord pour les utilisateurs :

img01

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 :

img09

Le panneau

Le panneau des utilisateurs apparaît ainsi :

img10

C'est la méthode index du contrôleur UserController qui l'affiche :
/**
 * Display a listing of the resource.
 *
 * @return Response
 */
public function index()
{
	return $this->indexSort('total');
}
On voit qu'il est fait appel à une autre fonction du contrôleur :
/**
 * Display a listing of the resource.
 *
 * @param  string  $role
 * @return Response
 */
public function indexSort($role)
{
    $counts = $this->user_gestion->counts();
    $users = $this->user_gestion->index(4, $role); 
    $links = $users->setPath('')->render();
    $roles = $this->role_gestion->all();

    return view('back.users.index', compact('users', 'links', 'counts', 'roles'));        
}
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 :

img12

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

img13

C'est la méthode index du repository UserRepository qui assure la gestion des données :
/**
 * Get users collection.
 *
 * @param  int  $n
 * @param  string  $role
 * @return Illuminate\Support\Collection
 */
public function index($n, $role)
{
	if($role != 'total')
	{
		return $this->model
		->with('role')
		->whereHas('role', function($q) use($role) {
			$q->whereSlug($role);
		})		
		->oldest('seen')
		->latest()
		->paginate($n);			
	}

	return $this->model
	->with('role')		
	->oldest('seen')
	->latest()
	->paginate($n);
}
C'est cette vue qui est utilisée :

img11

La partie du code qui gère le tableau est celui-ci :
<div class="table-responsive">
	<table class="table">
		<thead>
			<tr>
				<th>{{ trans('back/users.name') }}</th>
				<th>{{ trans('back/users.role') }}</th>
				<th>{{ trans('back/users.seen') }}</th>
				<th></th>
				<th></th>
			</tr>
		</thead>
		<tbody>
		  @include('back.users.table')
    </tbody>
	</table>
</div>
On voit qu'on inclut une autre vue (back/users/table.blade.php) :
@foreach ($users as $user)
	<tr {!! !$user->seen? 'class="warning"' : '' !!}>
		<td class="text-primary"><strong>{{ $user->username }}</strong></td>
		<td>{{ $user->role->title }}</td>
		<td>{!! Form::checkbox('seen', $user->id, $user->seen) !!}</td>
		<td>{!! link_to_route('user.show', trans('back/users.see'), [$user->id], ['class' => 'btn btn-success btn-block btn']) !!}</td>
		<td>{!! link_to_route('user.edit', trans('back/users.edit'), [$user->id], ['class' => 'btn btn-warning btn-block']) !!}</td>
		<td>
			{!! Form::open(['method' => 'DELETE', 'route' => ['user.destroy', $user->id]]) !!}
			{!! Form::destroy(trans('back/users.destroy'), trans('back/users.destroy-warning')) !!}
			{!! Form::close() !!}
		</td>
	</tr>
@endforeach

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 :

img14

Cette action est gérée en Javascript côté client avec envoi de la requête en Ajax :
// Seen gestion
$(document).on('change', ':checkbox', function() {    
  $(this).parents('tr').toggleClass('warning');
  $(this).hide().parent().append('<i class="fa fa-refresh fa-spin"></i>');
  var token = $('input[name="_token"]').val();
  $.ajax({
    url: '{!! url('userseen') !!}' + '/' + this.value,
    type: 'PUT',
    data: "seen=" + this.checked + "&_token=" + token
  })
  .done(function() {
    $('.fa-spin').remove();
    $('input[type="checkbox"]:hidden').show();
  })
  .fail(function() {
    $('.fa-spin').remove();
    var chk = $('input[type="checkbox"]:hidden');
    chk.show().prop('checked', chk.is(':checked') ? null:'checked').parents('tr').toggleClass('warning');
    alert('{{ trans('back/users.fail') }}');
  });
});
Avec une petite animation d'attente :

img15

C'est la méthode updateSeen du contrôleur UserController qui est chargée de la requête :
/**
 * Update the specified resource in storage.
 *
 * @param  Illuminate\Http\Request $request
 * @param  App\Models\User $user
 * @return Response
 */
public function updateSeen(
    Request $request, 
    $user)
{
    $this->user_gestion->update($request->all(), $user);

    return response()->json();
}
Il est fait appel à la méthode update du repository UserRepository :
/**
 * Update a user.
 *
 * @param  array  $inputs
 * @param  App\Models\User $user
 * @return void
 */
public function update($inputs, $user)
{        
    $user->confirmed = isset($inputs['confirmed']);

    $this->save($user, $inputs);
}
Ce sera la même méthode pour modifier d'autre 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 :
/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @param  \Illuminate\Routing\Router  $router
 * @return void
 */
public function boot(Router $router)
{
	parent::boot($router);

	$router->model('user', 'App\Models\User');
}
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. Ca 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.

Voir une fiche

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

img16

C'est la méthode show du contrôleur UserController qui est chargée de la requête :
/**
 * Display the specified resource.
 *
 * @param  App\Models\User
 * @return Response
 */
public function show(User $user)
{
    return view('back.users.show',  compact('user'));
}

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

img17

Avec ce code :

@extends('back.template')

@section('main')

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

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

@stop

Avec ce rendu :

img44

Créer un utilisateur

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

img19

C'est la méthode create du contrôleur UserController qui est chargée de la requête :
/**
 * Show the form for creating a new resource.
 *
 * @return Response
 */
public function create()
{
	return view('back.users.create', $this->role_gestion->getAllSelect());
}
Il est fait appel à la méthode getAllSelect du repository RoleRepository :
/**
 * Get roles collection.
 *
 * @param  App\Models\User
 * @return Array
 */
public function getAllSelect()
{
    $select = $this->all()->lists('title', 'id');

    return compact('select');
}
En effet on a besoin de la liste des rôles pour le formulaire. Le contrôleur génère la vue :

img20

Avec ce code :
@extends('back.template')

@section('main')

	<!-- Entête de page -->
	@include('back.partials.entete', ['title' => trans('back/users.dashboard'), 'icone' => 'user', 'fil' => link_to('user', trans('back/users.Users')) . ' / ' . trans('back/users.creation')])

	<div class="col-sm-12">
		{!! Form::open(['url' => 'user', 'method' => 'post', 'class' => 'form-horizontal panel']) !!}	
			{!! Form::control('text', 0, 'username', $errors, trans('back/users.name')) !!}
			{!! Form::control('email', 0, 'email', $errors, trans('back/users.email')) !!}
			{!! Form::control('password', 0, 'password', $errors, trans('back/users.password')) !!}
			{!! Form::control('password', 0, 'password_confirmation', $errors, trans('back/users.confirm-password')) !!}
			{!! Form::selection('role', $select, null, trans('back/users.role')) !!}
			{!! Form::submit(trans('front/form.send')) !!}
		{!! Form::close() !!}
	</div>

@stop
Ce qui donne ce formulaire :

img21

La méthode store du contrôleur UserController est chargée de gérer la soumission :
/**
 * Store a newly created resource in storage.
 *
 * @param  App\requests\UserCreateRequest $request
 *
 * @return Response
 */
public function store(
	UserCreateRequest $request)
{
	$this->user_gestion->store($request->all());

	return redirect('user')->with('ok', trans('back/users.created'));
}
La validation est assurée par la requête de formulaire UserCreateRequest :
<?php namespace App\Http\Requests;

class UserCreateRequest extends Request {

	/**
	 * Get the validation rules that apply to the request.
	 *
	 * @return array
	 */
	public function rules()
	{
		return [
			'username' => 'required|max:30|alpha|unique:users',
			'email' => 'required|email|unique:users',
			'password' => 'required|confirmed|min:8'
		];
	}

}

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

/**
 * Create a user.
 *
 * @param  array  $inputs
 * @param  int    $confirmation_code
 * @return App\Models\User 
 */
public function store($inputs, $confirmation_code = null)
{
    $user = new $this->model;

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

    if($confirmation_code) {
        $user->confirmation_code = $confirmation_code;
    } else {
        $user->confirmed = true;
    }

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

    return $user;
}
Puis le contrôleur affiche à nouveau la liste avec un message :

img22

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

img23

Modifier un utilisateur

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

img24

C'est la méthode edit du contrôleur UserController qui est chargée de la requête :
/**
 * Show the form for editing the specified resource.
 *
 * @param  App\Models\User
 * @return Response
 */
public function edit(User $user)
{
    return view('back.users.edit', array_merge(compact('user'), $this->role_gestion->getAllSelect()));
}

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

img25

Avec ce code :

@extends('back.template')

@section('main')

	<!-- Entête de page -->
	@include('back.partials.entete', ['title' => trans('back/users.dashboard'), 'icone' => 'user', 'fil' => link_to('user', trans('back/users.Users')) . ' / ' . trans('back/users.edition')])

	<div class="col-sm-12">
		{!! Form::model($user, ['route' => ['user.update', $user->id], 'method' => 'put', 'class' => 'form-horizontal panel']) !!}
			{!! Form::control('text', 0, 'username', $errors, trans('back/users.name')) !!}
			{!! Form::control('email', 0, 'email', $errors, trans('back/users.email')) !!}
			{!! Form::selection('role', $select, $user->role_id, trans('back/users.role')) !!}
			{!! Form::submit(trans('front/form.send')) !!}
		{!! Form::close() !!}
	</div>

@stop

Avec ce rendu :

img45

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 :

/**
 * Update the specified resource in storage.
 *
 * @param  App\requests\UserUpdateRequest $request
 * @param  App\Models\User
 * @return Response
 */
public function update(
    UserUpdateRequest $request,
    $user)
{
    $this->user_gestion->update($request->all(), $user);

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

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

<?php namespace App\Http\Requests;

class UserUpdateRequest extends Request {

	/**
	 * Get the validation rules that apply to the request.
	 *
	 * @return array
	 */
	public function rules()
	{
		$id = $this->user->id;
		return $rules = [
			'username' => 'required|max:30|alpha|unique:users,username,' . $id, 
			'email' => 'required|email|unique:users,email,' . $id
		];
	}

}

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 :

/**
 * Update a user.
 *
 * @param  array  $inputs
 * @param  App\Models\User $user
 * @return void
 */
public function update($inputs, $user)
{        
    $user->confirmed = isset($inputs['confirmed']);

    $this->save($user, $inputs);
}

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

img27

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

Supprimer un utilisateur

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

img28

C'est la méthode destroy du contrôleur UserController qui est chargée de la requête :
/**
 * Remove the specified resource from storage.
 *
 * @param  App\Models\user $user
 * @return Response
 */
public function destroy(User $user)
{
    $this->user_gestion->destroyUser($user);

    return redirect('user')->with('ok', trans('back/users.destroyed'));
}
Côté client on affiche quand même un petit message en Javascript par sécurité :

img29

Il est fait appel à la méthode destroyUser du repository UserRepository :
/**
 * Destroy a user.
 *
 * @param  App\Models\User $user
 * @return void
 */
public function destroyUser(User $user)
{
    $user->comments()->delete();
    
    $user->delete();
}

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

On affiche un message de confirmation pour l'administrateur :

img30

Noms des rôles

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

img31

C'est la méthode getRoles du contrôleur UserController qui est chargée de la requête :
/**
 * Display the roles form
 *
 * @return Response
 */
public function getRoles()
{
	$roles = $this->role_gestion->all();

	return view('back.users.roles', compact('roles'));
}
Il est fait appel à la méthode all du repository RoleRepository :
/**
 * Get all roles.
 *
 * @return Illuminate\Support\Collection
 */
public function all()
{
	return $this->role->all();
}

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

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

img32

Avec ce code :

@extends('back.template')

@section('main')

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

	<div class="col-sm-12">
		@if(session()->has('ok'))
			@include('partials/error', ['type' => 'success', 'message' => session('ok')])
		@endif
		{!! Form::open(['url' => 'user/roles', 'method' => 'post', 'class' => 'form-horizontal panel']) !!}	
			@foreach ($roles as $role) 
				{!! Form::control('text', 0, $role->slug, $errors, trans('back/roles.' . $role->slug), $role->title) !!}
			@endforeach
			{!! Form::submit(trans('front/form.send')) !!}
		{!! Form::close() !!}
	</div>

@stop

Et ce rendu :

img33

On peut donc ici changer les noms.

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

/**
 * Update roles
 *
 * @param  App\requests\RoleRequest $request
 * @return Response
 */
public function postRoles(RoleRequest $request)
{
	$this->role_gestion->update($request->except('_token'));
	
	return redirect('user/roles')->with('ok', trans('back/roles.ok'));
}

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

<?php namespace App\Http\Requests;

class RoleRequest extends Request {

	/**
	 * Get the validation rules that apply to the request.
	 *
	 * @return array
	 */
	public function rules()
	{
		return [
			'admin' => 'required|alpha|max:50',
			'redac' => 'required|alpha|max:50',
			'user'  => 'required|alpha|max:50'
		];
	}

}

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

/**
 * Update roles.
 *
 * @param  array  $inputs
 * @return void
 */
public function update($inputs)
{
	foreach ($inputs as $key => $value)
	{
		$role = $this->role->where('slug', $key)->firstOrFail();
		$role->title = $value;
		$role->save();
	}
}

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 :

img34

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



Par bestmomo

Nombre de commentaires : 13