Dans cette série d’articles, nous allons créer ensemble un site complet avec Laravel 12. Ce premier projet consiste en la réalisation d’une galerie photo qui devra avoir ces caractéristiques :
- Présenter des photos, classées en catégories (ou sous galeries)
- Possibilité de créer des articles, tuto de photographie
- Avoir une interface d’administration (backend) permettant d’ajouter des photos, des sous galeries et des articles facilement.
Une fois le design du site fait pour les pages d’accueil, de la galerie, du blog, de la page « A propos » et de contact, nous allons directement installer Laravel.
Pour info : je développe sous Windows 11 avec WSL2, serveur Apache 2, PHP 8.3
Installation et configuration de Laravel 12

Pour commencer il est nécessaire d’avoir « Composer » installé sur votre distribution WSL 2. Composer est le gestionnaire de paquets pour PHP. C’est l’outil qui nous permet d’installer le framework Laravel lui-même, ainsi que toutes les bibliothèques (packages) externes dont notre projet aura besoin. Nous aurons aussi besoin de NPM. Si il n’est pas disponible sur ton système, rendez-vous ici : GitHub – nvm-sh/nvm: Node Version Manager – POSIX-compliant bash script to manage multiple active node.js versions.
Pour installer Laravel, commence par installer l’installeur de Laravel (si ce n’est pas déjà fait) :
composer global require laravel/installerEnsuite dans le répertoire www de ton serveur web :
laravel new nom_du_projetRéponds aux questions :
- « Which starter kit would you like to install? » : « None »
- « Which testing framework do you prefer? » : « PHPUnit »
- « Which database will your application use? » : « MySQL »
- « Default database updated. Would you like to run the default database migrations? » : « No »
- « Would you like to run npm install and npm run build? » : « Yes »
Il faut ensuite configurer Laravel pour l’utilisation des bases de données. Pour ce faire il y a un fichier .env à la racine du site. Afin d’être plus pratique, nous allons créer 2 fichiers .env. Le premier sera pour le serveur de production (la version finale du site en ligne) et le deuxième .env.staging pour le serveur de développement sous WSL2. Dans chacun des 2 fichiers (ou un seul suivant ce que tu souhaite faire), cherche et complète les lignes suivantes suivants la configuration nécessaire (production / développement) :
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=nom_de_ta_base
DB_USERNAME=nom_de_ton_utilisateur
DB_PASSWORD=ton_mot_de_passePendant qu’on y est nous pouvons aussi modifier les valeurs de :
APP_NAME=nom_de_ton_projet
APP_ENV=local #ou staging si tu es en mode développement
APP_DEBUG=false #ou true en staging
APP_URL=url_de_ton_site #ou 127.0.0.1:8000 en staging
APP_LOCALE=fr
# Pour l'envois des mails, nous pouvons aussi configurer :
MAIL_HOST=ton_serveur_mail
MAIL_PORT=le_port_de_ton_serveur
MAIL_USERNAME=ton_nom_utilisateur
MAIL_PASSWORD=ton_mot_de_passe
MAIL_FROM_ADDRESS="ton_adresse_mail_expéditeur"
MAIL_FROM_NAME="${APP_NAME}"Apache (partie falcultative)
Laravel est livré avec son propre serveur Web. Toutefois pour afficher le site en local sans démarrer le serveur de Laravel il faut apporter quelques modifs à la configuration d’Apache. Il faut dire à Laravel quel fichier d’environnement utiliser suivant le serveur sur lequel nous nous trouvons. Pour cela nous allons définir une variable d’environnement dans le fichier /etc/apache2/sites-enabled/ton_projet.conf. Ajoute cette ligne à la fin du fichier avant </VirtualHost>.
SetEnv APP_ENV stagingNous allons aussi activer le module de réécriture des URL d’Apache ce sera plus joli et plus SEO-Friendly. En principe c’est déjà le cas, mais on sais jamais.
sudo a2enmode rewritePuis on redémarre Apache:
sudo systemctl restart Apache2Artisan et Vite
Ok, cool. Nous avons maintenant presque une application Laravel fonctionnelle. Il nous faut encore installer les tables requises par Laravel dans la base de données. Rien de plus simple, cela se fait en une seule ligne de commande :
php artisan migrateIl nous est maintenant possible de tester notre application. Il suffit de taper cette commande :
composer run devCela aura pour effet de démarrer le serveur NPM pour la gestion des dépendances du frontend et le serveur de Laravel. Ceci est équivalent aux commandes npm run dev et php artisan serve.
Tu peux maintenant tu connecter à l’adresse http://127.0.0.1:8000 et tu pourras y voir la page d’accueil de ton application Laravel.

Concept Clé : Artisan & Vite Laravel est fourni avec Artisan, une interface en ligne de commande qui simplifie de nombreuses tâches. Vite est un outil moderne qui gère nos « assets » front-end (CSS, JavaScript). En développement, nous avons besoin de deux serveurs qui tournent en parallèle : Le serveur PHP de Laravel pour la logique backend et le serveur de Vite pour compiler notre CSS à la volée.
Travailler avec Tailwind CSS
Nous allons aussi intégrer directement Tailwind à notre projet. Cela nous permettra de construire des interfaces rapidement sans quitter la partie HTML. Exécute la commande suivante dans le répertoire du projet :
npm install tailwindcss @tailwindcss/viteIl faut ensuite modifier le fichier de configuration de vite afin d’utiliser Tailwind et les Lucide icons. Modifions le fichier à la racine du site vite.config.js :
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
});Et le fichier de configuration à la racine du projet /tailwind.config.js :
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
],
darkMode: 'class',
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
},
},
plugins: [],
}Blade
Pour la structure HTML du site, Laravel utilise un puissant système de templates nommé Blade. Les fichiers templates doivent être placés dans resources/views. Les règles CSS seront dans le fichier resources/css/app.css par défaut.
Pour éviter de copier / coller sur chaque page, nous pouvons créer un composant app.blade.php dans le dossier resources/views/components/layouts. Pour que cela fonctionne correctement nous pouvons utiliser Artisan pour générer les fichiers nécessaires :
php artisan make:component Layouts/App Nous allons maintenant ouvrir les fichiers qui ont été créés et les modifier. Commençons par le fichier resources/views/components/layouts/app.blade.php c’est le fichier principal de notre thème. Le thème utilisé ici sera très simple. A toi de l’améliorer pour correspondre à tes attentes.
@props(['title' => 'Titre de la page par défaut'])
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="light">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ $title }}</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Vite Assets -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200 transition-colors duration-300 antialiased">
<x-header />
<main>
{{ $slot }}
</main>
<x-footer />
</body>
</html>Crée le fichier resources/views/components/header.blade.php et ajoute :
<nav class="container mx-auto px-6 py-4 flex items-center justify-between flex-wrap">
<!-- Logo -->
<div class="flex-shrink-0">
<a href="#" class="text-2xl font-bold text-gray-800 hover:text-blue-600 transition-colors">
Logo
</a>
</div>
<!-- hamburger -->
<div class="block md:hidden">
<button id="menu-btn" class="text-gray-800 focus:outline-none">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 6h16M4 12h16m-7 6h7"></path>
</svg>
</button>
</div>
<!-- Menu -->
<div id="mobile-menu" class="w-full md:flex md:items-center md:w-auto hidden md:flex-grow">
<div class="md:flex md:justify-center md:flex-grow md:space-x-6 text-center md:text-left">
<a href="#" class="block mt-4 md:mt-0 text-gray-600 hover:text-blue-600 transition-colors">Accueil</a>
<a href="#" class="block mt-4 md:mt-0 text-gray-600 hover:text-blue-600 transition-colors">À propos</a>
<a href="#" class="block mt-4 md:mt-0 text-gray-600 hover:text-blue-600 transition-colors">Services</a>
</div>
<div class="mt-4 md:mt-0 text-center md:text-left">
<a href="#"
class="inline-block bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-transform transform hover:scale-105">
Contact
</a>
</div>
</div>
</nav>Idem pour le fichier resources/views/components/footer.blade.php :
<div class="container mx-auto px-6 py-4">
<div class="text-center text-sm text-gray-400">
© 2025 Mon Entreprise. Tous droits réservés.
</div>
</div>Il faut encore créer la page d’accueil resources/views/pages/home.blade.php :
<x-layouts.app :title="Titre par défaut, à remplacer par la variable $title après la création des routes">
<div class="text-center">
<h1 class="text-4xl font-bold mb-4">Slogan du site</h1>
<p class="text-gray-600">Le contenu du site viendra ici.</p>
</div>
</x-layouts.app>Voilà la première page est maintenant visible, rends toi sur http://127.0.0.1:8000 pour admirer le résultat. (il se peut qu’il y a ait un message d’erreur, cela et dû au fait que la variable titre n’est pas définie, nous allons le faire dans l’étape des routes). Nos futurs fichiers .blade.php auront ensuite la structure suivante :
{{-- La page utilise le composant Layout --}}
<x-layouts.app title=$title>
<section>
<h1>Galeries</h1>
<p>Explorez mon travail à travers différentes collections thématiques.</p>
</section>
<section>
<div>
@forelse ($galleries as $gallery)
{{-- Boucle pour afficher les sous galeries --}}
@empty
<p>Aucune galerie à afficher pour le moment.</p>
@endforelse
</div>
</section>
</x-layouts.app>
Le fichier resources/views/welcome.blade.php peut être supprimé. Il a été généré automatiquement lors de l’installation de Laravel et il n’est plus nécessaire.
Concept Clé : Les composants. Pense à un composant comme à une balise HTML personnalisée que tu as créé toi-même. C’est plus clair, plus explicite et plus réutilisable.
D’autres instructions Blade (que nous reverrons plus tard)
1. Afficher des Données ({{ ... }})
C’est la fonction de base pour afficher le contenu d’une variable. L’avantage principal est que Blade sécurise automatiquement le contenu pour toi en échappant les caractères HTML, ce qui te protège contre les attaques XSS.
<h1>{{ $post->title }}</h1>
<p>{{ $post->excerpt }}</p>Mais si tu ne souhaite pas que la variable soit échappée automatiquement (attention à la sécurité) tu peux utiliser {!! $variable !!} et pour les commentaires {{-- Commentaire --}}.
2. Les Structures de Contrôle (@if, @foreach)
Nous pouvons utiliser toutes les structures de contrôle PHP classiques, mais avec la syntaxe plus propre de Blade.
- Les conditions (
@if,@else)
@if ($post->is_published)
<span class="badge-publie">Publié</span>
@else
<span class="badge-brouillon">Brouillon</span>
@endif- Les boucles (
@foreach)
@foreach ($photos as $photo) {{-- On peut utiliser $loop pour savoir où on est dans la boucle --}}
@if ($loop->first)
<p>Ceci est la première photo de la galerie.</p>
@endif
<img src="{{ $photo->image_path }}" alt="">
@endforeachIl existe aussi les boucles standards @for ($i = 0; $i < 10; $i++) … @endfor et @while (condition) … @endwhile.
- La boucle avec condition « vide » (
@forelse)
C’est un@foreachamélioré. Il permet d’afficher un message si la liste est vide, ce qui est très pratique.
@forelse ($photos as $photo)
@empty
Il n'y a pas encore de photo dans cette galerie.
@endforelseA noter qu’on peut aussi utiliser @empty ($variable) ... @endempty sans boucle et que @foreach ($collection as $item) … @endforeach fonctionnera aussi.
Variables de boucles
À l’intérieur d’une boucle @foreach ou @forelse, vous avez accès à la variable $loop :
$loop->index: L’index de l’itération (commence à 0).$loop->iteration: L’itération actuelle (commence à 1).$loop->first: Booléen,truesi c’est la première itération.$loop->last: Booléen,truesi c’est la dernière itération.$loop->count: Le nombre total d’éléments.$loop->parent: Fait référence à la variable$loopde la boucle parente (si imbriquée).@break: Arrête la boucle.@continue: Passe à l’itération suivante.
Il existe aussi @isset ($variable) ... @endisset qui s’exécute si la variable est définie. Il y a encore @unless (condition) ... @endunless qui est l’inverse de @if, c’est-à-dire qu’il exécutera le code si la condition est false.
Pour exécuter du code si l’utilisateur est connecté on utilisera @auth ... @endauth et si il ne l’est pas @guest ... @endguest.
On peut aussi filtrer en fonction de l’environnement de travail avec @production ... @endproduction et @env('local/staging') ... @endenv.
3. Les directives pour formulaires
Pratiques pour les attributs HTML :
@checked(condition): Ajoute l’attributcheckedsi la condition est vraie.@selected(condition): Ajoute l’attributselectedsi la condition est vraie.@disabled(condition): Ajoute l’attributdisabledsi la condition est vraie.@readonly(condition): Ajoute l’attributreadonlysi la condition est vraie.@required(condition): Ajoute l’attributrequiredsi la condition est vraie.
5. Les Composants Blade (<x-nom-du-composant>)
Comme nous l’avons vu les composants permettent de créer de véritables éléments réutilisables, comme si nous utilisions un framework JavaScript (Vue, React). C’est la nouvelle syntaxe de Laravel qui remplace les anciennes fonctions @include et @yield.
<x-component-name />: Appel d’un composant simple (ex:<x-alert />).<x-component-name :variable="$value" />: Passage de données au composant via des attributs.<x-component-name> ... </x-component-name>: Passage de contenu via la variable$slotpar défaut.<x-slot name="title"> ... </x-slot>: Passage de contenu dans un slot nommé (défini dans le composant).
6. Les Piles (ou stacks)
Utile pour charger des scripts ou des styles spécifiques à une page dans le layout principal.
@push('scripts')…@endpush: Ajoute du contenu à la fin d’une pile (ex: ajouter un<script>spécifique).@prepend('scripts')…@endprepend: Ajoute du contenu au début d’une pile.@stack('scripts'): (Placé dans le layout) Affiche tout le contenu qui a été « pushé » dans cette pile.@once…@endonce: Garantit qu’un bloc de code (souvent un@push) n’est exécuté qu’une seule fois, même s’il est inclus plusieurs fois (ex: dans une boucle).
7. Traductions
Pour un site multi-langue nous pouvons utiliser la fonction __(messages.welcome) qui fera référence au fichier lang/fr/messages.php ou fr est tiré du fichier .env.
return [
'welcome' => 'Bienvenue sur notre application !',
'bye' => 'À bientôt.',
];Il y aussi la possibilité d’utiliser des fichiers json. Mais la traduction dans Laravel justifie à elle seule un tuto complet. Reporte toi à la documentation officielle pour en savoir plus. Ou laisse un commentaire ci-dessous et j’en ferai peut-être un article à part.
8. Autres Directives Utiles
@csrf: Indispensable à mettre dans tous les formulaires pour la sécurité.@method('PUT'): (OuPATCH,DELETE) Simule une méthode HTTP différente, car les formulaires HTML ne supportent nativement queGETetPOST.@error('field_name')…@enderror: Affiche un message d’erreur de validation pour un champ spécifique.@php…@endphp: Permet d’écrire du code PHP brut. ⚠️ À utiliser avec parcimonie, car cela va à l’encontre de la séparation de la logique et de la présentation.@inject('service', 'App\Services\MyService'): Injecte un service (depuis le conteneur de services) dans la vue.- @vite([‘resources/css/app.css’, ‘resources/js/app.js’]) : Injection des dépendances par Vite.
C’est terminé pour la première étape de ce projet. Dans le prochaine article, nous allons mettre en place nos routes (les chemins d’accès aux fichiers). Cela se passe ici : https://www.skweb.ch/laravel/projet-realisation-galerie-photo-partie-2-les-routes/
En résumé
laravel new nom-du-projet
cd nom-du-projet
npm install
npm install tailwindcss @tailwindcss/vite
# Configurer base de donnée dans .env
php artisan migrate
composer run dev