Créer un blog basique qui contiendra des articles créer par des utilisateurs. Votre blog devra avoir les fonctionnalités suivantes:
Durant ce Workshop, différentes technologies seront utilisées pour la création du blog. Le but principal étant de s'initier au framework Laravel, ainsi, ne perdez pas de temps sur le front-end (aspect visuel) du site.
A la fin de ce workshop, vous aurez:
Durant ce projet, nous utiliserons un environnement pré-configurés sous Laragon.
Afin d'optimiser le temps sur le développement et non sur l'administration d'un serveur, nous avons pré-configurés tout ce dont vous aurez besoin.
Pour retrouver votre fichier où est installé Laravel, utilisez le bouton "Dossier www" qui vous y redirigera.
Votre serveur web est configuré par défaut sur le port 80.
Un gestionnaire MySQL (PhpMyAdmin) est configuré par défaut, disponible en cliquant sur le bouton "Base de données".
Configurations MySQL:
Hôte: localhost
Port: 3306
Utilisateur: root
Aucun mot de passe n'est configur
Vous pouvez y accéder en cliquant sur le bouton "Terminal". Les principales commandes que vous aurez besoin d'utiliser seront disponible sous votre systeme Windows.
Le framework Laravel met à votre disposition Artisan qui est une console vous permettant de générer et gérer votre site. Pour l'utiliser, il vous suffit d'être à la racine de votre projet et d'exécuter php artisan
tu verras alors apparaître la liste des commandes disponibles.
Cette console va donc nous permettre de générer les différentes parties de notre architecture MVC, à savoir: nos models, nos migrations, nos controllers, ...
Mais vous pourrez aussi interagir directement avec votre site: maintenance, task scheduling, mailings, routes, déploiement...
Testez par vous même comme cet outil peut être intéressant: php artisan down
Rendez-vous sur votre site et observez les changements. Pour sortir du mode maintenance, il vous suffit d'utiliser php artisan up
Imaginez maintenant le temps que vous auriez mit à réaliser un mode maintenance aussi user-friendly si vous n'utiliserez aucun framework ?
Pour commencer notre blog, il va falloir coder notre système d'authentification. Ainsi, différentes pages sont à ne pas oublier pour avoir un système complet et efficace:
Et si je te disais que tu avais 2 minutes pour faire ça ?
Et si je te disais que c'était vraiment faisable en 2 minutes ?
https://laravel.com/docs/7.x/authentication
Ce nom peut paraitre barbare mais c'est pourtant l'un des points fort de Laravel. Tout un système d'authentification complet est embarqué dans le framework.
Quel gain de temps...
A notre clavier, mettons ce que nous avons découvert en pratique: Artisan.
laravel/ui
qui contient toutes les views et routes que nous aurons besoin pour l'authentification: composer require laravel/ui
php artisan ui vue --auth
npm install
puis npm run dev
Et si je vous disais qu'en plus d'avoir générer tout le code d'authentification il avait fait encore mieux que ça ? Spécialement pour nous, Artisan vient de générer tout le contenu front-end sous Bootstrap ainsi que toutes les views.
Une petite visite sur: http://localhost/login pour observer le travail et le bien-être qu'un framework procure 😍
https://laravel.com/docs/7.x/migrations
Les migration sont un système permettant de gérer vos bases de données. C'est l'un des points essentiels pour ce genre de site afin de sauvegarder nos données. Les migrations permettent aussi de créer des schémas de bases de données plus ou moins complexes.
Toutes nos migrations se trouvent dans database/migrations/
Vous y retrouverez alors différents fichiers sous la forme 2014_20_12_000000_create_xxx_table.php
Ces fichiers comprennent une série d'instruction qui va ensuite permettre de générer et structurer votre base de donnée.
Pour pouvoir accéder aux commandes de migration (via Artisan), il faut impérativement configurer notre base de donnée. Sans cela, vous aurez une erreur vous disant que Laravel ne parvient pas à se connecter au serveur MySQL.
Les configurations de notre serveur se trouvent dans 1 seul et unique fichier: .env
Ce fichier étant assez intuitif, je te laisse ajuster les configurations à ta guise de manière à faire fonctionner le serveur MySQL.
L'authentification ayant été généré par Laravel, la migration pour les données des utilisateurs l'est aussi. Vous avez donc (si toutes les étapes ont été respectés) un ou plusieurs fichiers dans vos migrations.
Quelques commandes utiles:
php artisan migrate:status
: Aperçu de toutes vos migrations et de leur statut (migré ou non)
php artisan migrate
: Effectue les migrations qui n'ont pas encore été faites (function up()
)
php artisan migrate:rollback
: Vous permet de reverse vos migrations (function down()
) . Vous pouvez ajouter une option --step=X
pour appliquer ce rollback aux X dernières migrations.
Il ne vous reste donc plus qu'à valider le tout et effectuer votre première migration générée par Laravel Authentification.
Avant toute chose, il faut réfléchir à la meilleure structure de notre base de donnée pour permettre d'enregistrer toutes les données nécessaires et le plus proprement possible.
Dans notre cas, nous allons réaliser un blog. Nous aurons donc différents "modules" (que nous appelerons ultérieurement des models).
Ceci est (un example d') un schéma de notre base de donnée qui est représentée par 3 models:
On peut aussi apercevoir sur ce schéma des liens entre chaque models, c'est lien seront appelés relationships: https://laravel.com/docs/7.x/eloquent-relationships
Vous allez donc devoir créer ces 3 models ainsi que leurs migrations. Pour cela, une commande existe et fait tout en une seule fois: php artisan make:model -m Model
Actuellement, notre page ressemble à la page par défaut de Laravel.
Le contenu de cette page se trouve dans nos ressources: resources/views/welcome.blade.php
Nous allons pouvoir supprimer ce qui est à l'intérieur car le contenu proposé par Laravel ne correspond pas à ce que nous désirons, et le remplacer par ce code:
resources/views/welcome.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12">
<!--Our code here-->
</div>
</div>
</div>
@endsection
Quelques explications...
Chaque page est composée d'une route, d'un controller et d'une view.
routes/web.php
app/Http/Controllers
resources/views/
Pour information, une view se terminent toujours par l'extension .blade.php
et utilise le moteur de template Blade. Cela nous permet d'inclure des données, conditions, ... directement dans notre code HTML.
Ainsi, c'est pour cela que nous avons des balises qui commencent par @
, il s'agit donc du moteur Blade qui interprète cela en PHP ensuite lors de l'affichage.
@extends
: cette balise permet d'inclure un code d'un autre fichier (comparable en C à #include "/path"/
).@section('name') / @yield('name')
: ces 2 balises prennent en paramètre un string et permettent de créer des blocs de code. Ainsi, dans l'exemple ci-dessus on créer un bloc content
qui sera affiché lorsqu'on appellera @yield(‘conte
nt')à un endroit de notre code.Mise en page de la liste des articles
resources/views/welcome.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row mb-2">
<!-- Post 1 -->
<div class="col-md-6">
<div class="row border mb-4 shadow-sm h-md-250">
<div class="col p-4 d-flex flex-column position-static">
<h3 class="mb-0">Title</h3>
<div class="mb-1 text-muted">Date</div>
<p class="card-text mb-auto">Some content limited to 200 characters...</p>
<a href="#" class="stretched-link">Voir le post</a>
</div>
<div class="d-lg-block">
<img class="bd-placeholder-img" width="200" height="250" src="https://www.webnode.com/blog/wp-content/uploads/2016/10/Blog-intro.jpg">
</div>
</div>
</div>
<!-- End Post 1 -->
</div>
</div>
@endsection
Vous devriez obtenir le résultat suivant:
Restructuration de nos routes/views/controllers
Maintenant que nous avons une mise en page correcte de nos articles, il est temps de s'occuper de l'architecture de notre site qui est un peu en vrac. Des routes qui n'ont aucun sens: welcome, home... pourquoi ces noms ? Où est l'index ? Compliqué de s'y retrouver.
Par défaut, la view welcome
ne dispose pas de controller. Nous allons donc renommer cette route en index
et lui créer son controller.
php artisan make:controller IndexController
app/Http/Controllers/IndexController.php
routes/web.php
de manière à faire correspondre avec la fonction créer dans le controller correspondant.Et maintenant, afin d'avoir une architecture correcte de notre site. Nous allons renommer la view home
en user
et cette vue contiendra ainsi l'espace de l'utilisateur une fois connecté.
HomeController -> UserController
php artisan route:list
)./user
Maintenant que nous avons notre architecture correcte, nous allons pouvoir modifier notre menu et dans le menu déroulant nous allons ajouter "Mon compte" qui retournera vers /user
lorsque l'utilisateur est connecté.
-> Pas d'indice cette fois-ci, recherchez dans vos fichiers où se trouvent cela...
Affichage des données stockées
Il est temps d'afficher nos données stockées sur notre page "index" et rendre notre site dynamique avec les vrais articles que nous avons en base de donnée.
Pour cela, nous allons nous rendre dans notre controller correspondant et nous allons récupérer avec Eloquent nos différentes données.
La documentation officielle: https://laravel.com/docs/7.x/eloquent#retrieving-models
Comment envoyer des données à notre page ?
C'est très simple, il suffit de retourner ces mêmes données dans le view.
Exemple:
class IndexController extends Controller
{
public function index()
{
return view('index')
->with('variable', 'value');
}
}
Et dans notre view, nous pouvons récupérer notre variable de la manière suivante: {{ $variable }}
qui affichera "value".
Dans notre cas, nous récupérerons un Query Builder qui contiendra toutes nos valeurs. Pour le parcourir il suffit de faire un foreach.
Exemple:
@foreach ($queryBuilder as $element)
{{ $element->title }}
@endforeach
Notre site est basé sur la publication d'article, il nous reste donc à gérer la publication et la modification de nos articles.
Pour cela, nous utiliserons un CRUD qui signifie: Create, Read, Update, Delete. Laravel (et notamment Artisan) permettent de générer notre base de code, on appel cela un Resources Controller.
Plus d'informations sur la documentation officielle: https://laravel.com/docs/5.7/controllers#resource-controllers
Commençons!
Créer son CRUD en quelques étapes:
php artisan make:controller -r --model Post PostController
Route::resource('posts', 'PostController');
php artisan route:list
et vérifier que vos nouvelles routes sont disponibles.Tout se déroule dans le controller que nous venons de créer: app/Http/Controllers/PostController.php
Chaque fonction correspond à une route. Il est temps de remplir ces fonctions.
Que faire ?
Il est temps de créer les rendus (donnés en HTML ci-dessus) et de faire rediriger les fonctions correspondantes dans votre controller
Le rendu HTML de chaque page est donné ci-dessous:
resources/views/post/show.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row mb-2">
<div class="col-md-12 blog-main">
<div class="row border-bottom mb-4">
<div class="col-md-8">
<h3 class="pb-4 font-italic">
Article #[ID]
</h3>
</div>
<!-- Only for the creator of the post -->
<div class="col-md-4 text-right">
<form>
<a class="btn btn-outline-primary" href="{{ route('posts.edit', $post) }}">Modifier</a>
<button type="submit" class="btn btn-outline-danger">Supprimer</button>
</form>
</div>
<!-- End: Only for the creator of the post -->
</div>
<div class="blog-post">
<h2 class="blog-post-title">[Article title]</h2>
<p class="blog-post-meta">[Date], par <a href="#">[Author]</a></p>
<p>Content</p>
</div>
</div>
</div>
</div>
@endsection
resources/views/post/create.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="py-5 text-center">
<h2>Publication d'un article</h2>
<p class="lead">Remplir ce formulaire pour voir son article publié.</p>
</div>
<form>
@csrf
<div class="row">
<div class="col-md-12">
<div class="mb-3">
<label for="title">Titre</label>
<input type="text" id="title" name="title" placeholder="Entrez le titre de votre article..." required="required" class="form-control">
</div>
<div class="mb-3">
<label for="title">Contenu</label>
<textarea id="content" name="content" placeholder="Entrez le contenu de votre article..." rows="10" required="required" class="form-control"></textarea>
</div>
</div>
<div class="col-md-12 text-right">
<button type="reset" class="btn btn-outline-secondary">Annuler</button>
<button type="submit" class="btn btn-outline-primary">Publier l'article</button>
</div>
</div>
</form>
</div>
@endsection
resources/views/post/edit.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="py-5 text-center">
<h2>Edition d'un article</h2>
<p class="lead">Article #[ID]</p>
</div>
<form>
@csrf
<div class="row">
<div class="col-md-12">
<div class="mb-3">
<label for="title">Titre</label>
<input type="text" id="title" name="title" value="[VALUE TITLE]" placeholder="Entrez le titre de votre article..." required="required" class="form-control">
</div>
<div class="mb-3">
<label for="content">Contenu</label>
<textarea id="content" name="content" placeholder="Entrez le contenu de votre article..." rows="10" required="required" class="form-control">[VALUE CONTENT]</textarea>
</div>
</div>
<div class="col-md-12 text-right">
<button type="reset" class="btn btn-outline-secondary">Annuler</button>
<button type="submit" class="btn btn-outline-primary">Editer l'article</button>
</div>
</div>
</form>
</div>
@endsection
Nous avons maintenant nos 3 pages: création, affichage et édition d'un article.
Cette étape est cruciale pour tout site internet, la réalisation des formulaires.
Commençons par la création d'un article, profitez car sur celui là vous serez bien guidé!
resources/views/post/create.blade.php
<form action="{{ route('posts.store') }}" method="POST">
@csrf
@method('POST')
</form>
Voici un exemple de form. Quelques explications:
action=".."
: vous permet d'envoyer la requête vers une URL. Par défaut, si vous ne le mettez pas, la requête sera envoyé sur la page actuelle.method=".."
: spécifié le type de requête, il en existe plusieurs (POST, GET, HEAD, ...). Pour connaître le type de requête correspondant à la route, vous pouvez utiliser la commande php artisan route:list
Une fois que nous appuyons sur un button de type submit
, la requête sera alors envoyé à notre controler.
app/Http/Controllers/PostController.php
public function store(Request $request)
{
dd($request->input());
}
Vous pourrez donc apercevoir, une fois le formulaire envoyé, des données similiaires à :
Nous retrouvons donc notre token CSRF, notre method et les différents composants de notre formulaire (dans notre cas: title, content).
Maintenant que nous avons toutes les données de notre formulaire, il nous reste qu'à vérifier qu'elles soient correctes et les enregistrer en base de donnée!
Pour cela nous utiliserons les validators: https://laravel.com/docs/5.8/validation
Voici le validator pour la création d'un post:
app/Http/Controllers/PostController.php
public function store(Request $request)
{
$request->validate([
'title' => 'required|min:5|unique:posts',
'content' => 'required|min:15',
]);
dd("form ok");
}
Affichage des erreurs dans la view:
resources/views/posts/create.blade.php
@if ($errors->any())
<div class="alert alert-danger">
<b>Erreurs:</b>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
Maintenant que nous avons la validation de notre formulaire, nous n'avons plus qu'à enregistrer en base de donnée notre formulaire et retourner l'utilisateur sur le post.
app/Http/Controllers/PostController.php
public function store(Request $request)
{
// On vérifie que les données du formulaires sont correctes
$request->validate([
'title' => 'required|min:5|unique:posts', // On vérifie que l'input "title" est présente, avec 5 char minimum et n'est pas utilisé par un autre article.
'content' => 'required|min:15', // On vérifie que l'input "content" est présente.
]);
// On enregistre les données
$post = Post::create([
'user_id' => Auth::user()->id, // 'user_id' de Post devient l'id de l'utilisateur actuel (celui qui créer le post).
'title' => $request->input('title'), // On enregistre le titre
'content' => $request->input('content'), // On enregistre le contenu
]);
return (redirect()->route('posts.show', $post)); // On redirige l'utilisateur vers l'article qui vient d'être créer
}
Nous avons donc fini de coder la création d'un article. Ce code vous permettra de comprendre le fonctionnement.
C'est à vous cette fois-ci! Vous avez les clés en mains pour éditer votre article existant.
La suppression d'un article est un peu différente, il s'agit d'un formulaire sans aucun input.
La pratique consiste donc à déclarer une nouvelle balise qui redirige vers la route correspondante et y insérer à l'intérieur notre
.
Vous avez maintenant les clefs en mains!
Maintenant que tous nos formulaires sont opérationnels, il est temps d'avoir un affichage correct de notre article. Il est donc impératif de remplir tous les champs dans notre view posts.show
.
Pour cela, une problématique va se poser. Le champs [Author]
qui requiert d'afficher le nom d'utilisateur du créateur de l'article. Pour cela, nous utiliseront une relationships de type one-to-one.
La documentation est assez explicite pour vous laissez en autonomie!
Félicitations, vous avez réalisé votre première application web sous Laravel!
Vous avez maintenant les bases pour vous initier au framework et apprendre de plus en plus par vous même. Ce framework vous économisera beaucoup de temps sur le développement de vos applications.
Vous avez maintenant les clés en mains pour poursuivre vers la seconde étape du workshop: la partie intermédiaire qui aura lieu prochainement au Hub Epitech.
N'hésitez pas à améliorer votre blog: