Ici, nous allons donc réaliser :
- La gestion des utilisateurs
- La gestion des posts
- La gestion des commentaires signalés
Cela implique de gérer pour chacun :
- Les droits d'accès
- Le CRUD
- Les vues
Ça fait beaucoup ! Je vais arriver à faire ça ?
Encore une fois, Laravel nous simplifie énormément le travail. Et puis, je suis là !
Un point sur le design
Avant d'attaquer, j'aimerais faire un point rapide sur le design. Si tu as testé la partie authentification (ce que je t'encourage à faire), tu auras remarqué que du style est déjà appliqué sur les formulaires et sur le panneau d'administration qui apparaissait post-connexion. Ce style a été généré automatiquement après avoir utilisé la commande npm run dev. Pour styliser ses pages, le framework utilise la technologie TailwindCSS. En installant Laravel Breeze, nous avons installé tout ce qu'il fallait pour utiliser cette technologie !
Ça a l'air bien pratique TailwindCSS !
En effet, et c'est pour cela que nous allons l'utiliser pour réaliser le design (simple, ce n'est pas le coeur du tutoriel non plus) de notre blog.
À savoir qu'il est également possible d'utiliser Laravel Breeze avec des technologies plus avancées comme des frameworks Frontend (vue.js, react) en passant des paramètres spécifiques lors de la commande php artisan breeze:install.
Créons nos routes
La première des étapes pour avoir un panneau d'administration (et pour avoir n'importe quelle partie de notre site d'ailleurs) est évidemment de définir les routes. Sur Laravel, beaucoup de possibilités nous sont offertes. On va voir ensemble les plus utilisées.
Rendez-vous dans le dossier routes et dans le fichier web.php. C'est dans ce fichier-ci qu'on va renseigner toutes les routes qui nous intéressent !
Et les autres fichiers on ne s'en sert pas ?
Le fichier api sert aux routes qui seront consommées par du javascript, ça ne nous intéresse pas dans le cadre de notre blog. De même pour les fichiers channels.php et console.php qui nous serviraient respectivement à gérer des évènements de Broadcast et à gérer des commandes artisan.
Quant à auth.php, on l'utilise, il a été généré par Laravel Breeze et il est inclus dans web.php ;)
Ok c'est compris ! Je remarque que dans le fichier web.php, il y a déjà une route qui parle du panneau d'administration...
Tu parles sans doute de celle-ci ?
{"language":"application/x-httpd-php","content":"<?php\n// Reste du code\n\nRoute::get('/dashboard', function () {\n return view('dashboard');\n})->middleware(['auth'])->name('dashboard');\n\n// Reste du code\n","filename":"web.php"}
En effet !
C'est bien que tu l'aies vue. Nous allons maintenant décrypter ce morceau de code.
On remarque déjà l'utilisation d'une méthode statique de la classe Route fournie par Laravel. Cette méthode s'appelle get.
On fournit à cette méthode 2 paramètres : le premier est la route en elle-même, c'est à dire ce qui va s'afficher dans l'URL. Ensuite, c'est le callback, c'est à dire ce qui va être exécuté quand on arrivera sur cette URL (ou route).
Dans le cas de notre panneau d'administration (cette route vient Breeze) Laravel a donc déjà défini la route /dashboard. Quand on y accède, on retourne une vue grâce à return view('nom de la vue').
Mais attends, view() c'est une fonction, je ne la vois définie nulle part !
En fait, elle est définie mais... Tu ne la vois pas. C'est ce que Laravel appelle un helpeur. En réalité, dans Laravel tu trouveras plein de fonctions définies globalement qui retournent des instances de classes ou des méthodes de classes. C'est très pratique ! Donc pas d'inquiétude, view() existe bien ;)
Super pratique ! Mais il y a encore 2 choses que je ne comprends pas. À quoi sert "middleware(['auth'])->name('dashboard')" ?
En fait, la méthode statique get et toutes les autres de notre classe Route sont très pratiques car elles retournent l'instance de Route, on peut donc mettre une suite de méthodes comme suit : Route::get()->methode1()->methode2()->methode3...
La méthode middleware() permet d'assigner un Middleware à la route, c'est à dire, pour faire simple, un contrôle d'accès définit dans une classe dont on passe le nom en paramètre (dans le cas, c'est "auth").
La méthode name() permet de nommer une route. C'est très pratique pour faire des liens vers cette route dans notre application sans se soucier d'où on est.
C'est encore un peu flou mais je suppose que ça va rentrer à force de pratique.
Oui, ne t'en fais pas.
Quelque chose me gêne quand même... Où est le controller dans tout ça ? On retourne une vue sans passer par un contrôleur !
Tu as vu juste. Cela a deux avantages :
- Déjà, c'est plus rapide à écrire !
- Ensuite, l'affichage de la page sera plus rapide qu'en passant par un contrôleur (car Laravel va charger moins de classes, faire moins d'actions...). On peut donc faire comme ça si on veut des performances plus intéressantes.
Cependant, pour gérer nos users, posts et commentaires, on aura besoin de contrôleurs ! On va donc commencer par créer notre premier contrôleur grâce à artisan :
{"language":"shell","content":"php artisan make:controller UsersController","filename":"console"}
On peut retrouver notre contrôleur dans app -> Http -> Controllers.
Parfait, maintenant faisons notre première route. On va commencer par simplement vouloir lister tous nos utilisateurs.
{"language":"application/x-httpd-php","content":"<?php\n\nuse Illuminate\\Support\\Facades\\Route;\nuse App\\Http\\Controllers\\UsersController;\n\n// Autres routes\n\nRoute::get('/users', [UsersController::class, 'index'])->middleware()->name('users');\n\nrequire __DIR__.'/auth.php';\n","filename":"web.php"}
Pour appeler un contrôleur et une méthode, on renseigne en deuxième paramètre la classe et le nom de sa méthode, tout simplement.
J'ai volontairement laissé vide "middleware()". Il faut que nous nous posions une question... Qui doit pouvoir accéder à tous les utilisateurs du site ? Et de manière globale, qui doit pouvoir accéder au panneau d'admin ?
Les administrateurs, facile !
Exactement. Il faut donc créer un middleware qui contrôlera que l'utilisateur qui essaie d'accéder à la route est bien un administrateur.
{"language":"shell","content":"php artisan make:middleware Admin","filename":"console"}
Rendez-vous maintenant dans app -> Http -> Middleware -> Admin.
Le contenu de classe est le suivant :
{"language":"application/x-httpd-php","content":"<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\n\nclass Admin\n{\n /**\n * Handle an incoming request.\n *\n * @param \\Illuminate\\Http\\Request $request\n * @param \\Closure(\\Illuminate\\Http\\Request): (\\Illuminate\\Http\\Response|\\Illuminate\\Http\\RedirectResponse) $next\n * @return \\Illuminate\\Http\\Response|\\Illuminate\\Http\\RedirectResponse\n */\n public function handle(Request $request, Closure $next)\n {\n return $next($request);\n }\n}\n","filename":"Admin.php"}
La méthode handle() est celle appelée quand on assigne un middleware à une route. C'est donc dedans qu'on agit. Le premier paramètre passé automatiquement par Laravel est la requête qu'on cherche à exécuter (on a donc plein d'infos sur la route, le contexte, l'utilisateur connecté...) et le second, passé automatiquement lui aussi, est ce qu'on doit faire si l'on passe le contrôle d'accès définit dans la méthode.
Nous, c'est très simple. On veut simplement vérifier que notre utilisateur courant est administrateur. Et heureusement, le paramètre $request a une méthode user() qui nous retourne toutes les infos sur l'utilisateur connecté, notamment la valeur du booléen "admin" qu'on a mis dans base dans la table users !
{"language":"application/x-httpd-php","content":"<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse App\\Enums\\UserRole;\n\nclass Admin\n{\n /**\n * Handle an incoming request.\n *\n * @param \\Illuminate\\Http\\Request $request\n * @param \\Closure(\\Illuminate\\Http\\Request): (\\Illuminate\\Http\\Response|\\Illuminate\\Http\\RedirectResponse) $next\n * @return \\Illuminate\\Http\\Response|\\Illuminate\\Http\\RedirectResponse\n */\n public function handle(Request $request, Closure $next)\n {\n if($request->user()->role === UserRole::Admin) {\n return $next($request);\n }\n abort(403);\n }\n}\n","filename":"Admin.php"}
Super simple n'est-ce pas ? Si on est admin, on laisse passer, sinon on retourne une erreur 403 (code HTTP 403 qui indique que la requête n'est pas autorisée (voir les codes HTTP)). Je ne rentre pas plus dans les détails, ce cours est avant tout une introduction.
Super simple, peut être pas. Mais j'arrive à comprendre !
Parfait. Avant de pouvoir utiliser ce middleware, il faut simple dire à Laravel que l'on peut l'assigner à des routes. Pour ça rendez-vous dans app -> Http -> Kernel.php et modifier le tableau $routeMiddleware comme suit :
{"language":"application/x-httpd-php","content":"<?php\n\nnamespace App\\Http;\n\nuse Illuminate\\Foundation\\Http\\Kernel as HttpKernel;\n\nclass Kernel extends HttpKernel\n{\n // Pleiiin de code\n\n /**\n * The application's route middleware.\n *\n * These middleware may be assigned to groups or used individually.\n *\n * @var array<string, class-string|string>\n */\n protected $routeMiddleware = [\n 'auth' => \\App\\Http\\Middleware\\Authenticate::class,\n 'auth.basic' => \\Illuminate\\Auth\\Middleware\\AuthenticateWithBasicAuth::class,\n 'cache.headers' => \\Illuminate\\Http\\Middleware\\SetCacheHeaders::class,\n 'can' => \\Illuminate\\Auth\\Middleware\\Authorize::class,\n 'guest' => \\App\\Http\\Middleware\\RedirectIfAuthenticated::class,\n 'password.confirm' => \\Illuminate\\Auth\\Middleware\\RequirePassword::class,\n 'signed' => \\Illuminate\\Routing\\Middleware\\ValidateSignature::class,\n 'throttle' => \\Illuminate\\Routing\\Middleware\\ThrottleRequests::class,\n 'verified' => \\Illuminate\\Auth\\Middleware\\EnsureEmailIsVerified::class,\n 'admin' => \\App\\Http\\Middleware\\Admin::class, // Ici notre middleware ! \n ];\n}\n","filename":"Kernel.php"}
Et maintenant, on peut compléter notre route ;)
{"language":"application/x-httpd-php","content":"<?php\nRoute::get('/users', [UsersController::class, 'index'])->middleware(['auth', 'admin'])->name('users');","filename":"web.php"}
Mais on n'a toujours pas réalisé la méthode index de UsersController ?
Non, on s'occupera des méthodes plus tard. Mais si tu veux, tu peux mettre un echo quelconque dans une méthode index() que tu écris dans UsersController pour voir le résultat lorsque tu vas sur https://tonsite.fr/users. Si tu n'es pas connecté, cela te ramènera vers le formulaire de connexion (grâce au middleware auth). Si tu l'es et que tu es admin (si tu utilises l'utilisateur créé grâce au factory dans le chapitre précédent dédié), dans ce cas la page s'affichera. Sinon, tu auras une erreur 403 ;).
Tu as tenu jusqu'ici, félicitations ! Va boire un café, méditer sur tout ça, et on se revoit après pour créer la suite de nos routes...
Je vais faire ça tu as raison, je reviens après !
Bilan de cette partie :
J'ai terminé cette partie - Le rôle des fichiers dans le dossier route
- L'utilisation de Route::get
- Le nommage des routes
- L'utilisation simple des middlewares