Architecture générale de l'application
Documentation complète de l'architecture modulaire de l'application Laravel, avec séparation claire entre le cœur de l'application et les modules spécifiques.
Structure générale
app/
Logique liée à l'application elle-même, le cœur fonctionnel de base.
- •
Http/Controllers– Contrôleurs principaux - •
Livewire– Composants Livewire de base - •
Models– Modèles principaux (User, Page) - •
Services– Services généraux - •
Filament– Configuration Filament - •
Events– Événements globaux
app/Specifics/
Modules annexes au site de base, fonctionnalités spécifiques et indépendantes.
- •
FeedbackHub– Gestion des retours - •
Blog– Système de blog - •
Shop– E-commerce - •
MediaManager– Gestion des médias - •
BlockBuilder– Constructeur de blocs - •
Appointments– Rendez-vous - •
Invoices– Facturation - •
FeedbackPerso– Retours personnels
app/Specifics/Shares/
Fichiers partagés entre différents modules pour éviter la duplication de code.
- •
Models– Modèles partagés - •
Enums– Énumérations communes - •
Concerns– Traits réutilisables
Structure d'un module Spec
Chaque module dans app/Specifics/ suit une structure standardisée pour maintenir la cohérence et faciliter la maintenance.
app/Specifics/ModuleName/
├── Actions/ # Actions métier (Create, Update, Delete, etc.)
├── Commands/ # Commandes Artisan spécifiques au module
├── Controllers/ # Contrôleurs HTTP si nécessaire
├── Enums/ # Énumérations spécifiques au module
├── Events/ # Événements déclenchés par le module
├── Factories/ # Factories pour les tests
├── Listeners/ # Écouteurs d'événements
├── Models/ # Modèles Eloquent
├── Observers/ # Observers Eloquent
├── Policies/ # Policies d'autorisation
├── Queries/ # Queries pour récupérer des données
├── Requests/ # Form Requests pour la validation
└── Services/ # Services métier complexes
Actions
Les Actions encapsulent la logique métier atomique. Elles sont utilisées par les Services, Controllers ou Composants Livewire.
Exemple :
CreateFeedbackAction::execute($user, $data)
Queries
Les Queries encapsulent les requêtes complexes pour récupérer des données. Elles peuvent inclure des filtres, des relations, etc.
Exemple :
GetFeedbackListQuery::execute(['type' => FeedbackType::FEATURE])
Services
Les Services orchestrent plusieurs Actions ou Queries pour une logique métier complexe. Ils sont généralement injectés dans les Controllers.
DTOs (Data Transfer Objects)
Les DTOs encapsulent des données complexes passées entre couches. Ils garantissent la structure et la validation des données.
Models & Enums
Les Modèles et Énumérations définissent la structure des données et les types de valeurs possibles.
Events & Listeners
Les Événements permettent de découpler les actions et les réactions. Les Listeners réagissent aux événements (notifications, logs, etc.).
Mode opératoire : Création d'une fonctionnalité de base
Guide étape par étape pour créer une nouvelle page ou fonctionnalité dans le cœur de l'application (app/).
Création des migrations / factories / seeder
Créer la structure de base de données et les données de test.
# Migration
php artisan make:migration create_examples_table
# Factory
php artisan make:factory ExampleFactory
# Seeder
php artisan make:seeder ExampleSeeder
Création des models / Enums
Définir les modèles Eloquent et les énumérations nécessaires.
# Model
php artisan make:model Example
# Enum (manuellement)
app/Enums/ExampleStatus.php
Création des FormRequest pour la validation
Créer les classes de validation pour les formulaires.
php artisan make:request StoreExampleRequest
php artisan make:request UpdateExampleRequest
Création de la route et du controller
Créer le contrôleur et définir les routes avec les middlewares nécessaires.
# Controller
php artisan make:controller ExampleController
# Route (routes/web.php ou routes/api.php)
Route::middleware(['auth'])->group(function () {
Route::resource('examples', ExampleController::class);
});
Création du service et des actions
Le contrôleur récupère les données validées et les envoie vers un Service qui utilise des Actions Laravel pour la logique métier.
# Service (app/Services/)
app/Services/ExampleService.php
# Action (si logique complexe)
app/Actions/CreateExampleAction.php
# Dans le Controller
public function store(StoreExampleRequest $request, ExampleService $service)
{
$example = $service->create($request->validated());
return redirect()->route('examples.show', $example);
}
Création des vues Blade / Composants
Créer les vues Blade et les composants réutilisables.
# Vues Blade
resources/views/examples/
├── index.blade.php
├── create.blade.php
├── edit.blade.php
└── show.blade.php
# Composants (si nécessaire)
php artisan make:component ExampleCard
Création des assets front
Ajouter les styles CSS et scripts JavaScript nécessaires.
# CSS (resources/css/)
resources/css/examples.css
# JavaScript (resources/js/)
resources/js/examples.js
# Compiler les assets
npm run build
# ou
npm run dev
Mode opératoire : Création d'un module Spec
Guide étape par étape pour créer un nouveau module dans app/Specifics/.
Création de la structure du module
Créer la structure de dossiers du module et les migrations.
# Structure de dossiers
app/Specifics/ModuleName/
├── Actions/
├── Enums/
├── Models/
├── Requests/
└── ...
# Migration
php artisan make:migration create_module_name_table
Création des models / Enums
Définir les modèles et énumérations spécifiques au module.
# Model
php artisan make:model Specifics/ModuleName/Models/Example
# Enum
app/Specifics/ModuleName/Enums/ExampleStatus.php
Création des FormRequest
Créer les classes de validation dans le module.
php artisan make:request Specifics/ModuleName/Requests/StoreExampleRequest
Création des Actions
Créer les Actions qui encapsulent la logique métier.
# Action
app/Specifics/ModuleName/Actions/CreateExampleAction.php
class CreateExampleAction
{
public function execute(array $data): Example
{
return DB::transaction(function () use ($data) {
$example = Example::create($data);
event(new ExampleCreated($example));
return $example;
});
}
}
Création des Queries (si nécessaire)
Créer les Queries pour les requêtes complexes de récupération de données.
# Query
app/Specifics/ModuleName/Queries/GetExamplesQuery.php
class GetExamplesQuery
{
public function execute(array $filters = []): Collection
{
return Example::query()
->when($filters['status'] ?? null, fn($q, $status) =>
$q->where('status', $status))
->get();
}
}
Création des routes et contrôleurs
Créer les routes et contrôleurs (ou utiliser Livewire).
# Option 1 : Controller
php artisan make:controller Specifics/ModuleName/Controllers/ExampleController
# Option 2 : Livewire (recommandé)
php artisan make:livewire ModuleName/Examples/Index
# Route
Route::middleware(['auth'])->group(function () {
Route::get('/examples', Index::class)->name('examples.index');
});
Création des Events & Listeners
Créer les événements et écouteurs pour découpler les actions.
# Event
php artisan make:event Specifics/ModuleName/Events/ExampleCreated
# Listener
php artisan make:listener Specifics/ModuleName/Listeners/SendExampleNotification
# Enregistrer dans EventServiceProvider
Création des vues et composants
Créer les vues Blade et composants Livewire.
# Vues Livewire
resources/views/livewire/module-name/examples/
├── index.blade.php
└── create.blade.php
# Composants Blade réutilisables
resources/views/components/module-name/example-card.blade.php
Utilisation des fichiers partagés (Shares)
Utiliser les modèles, enums et concerns partagés pour éviter la duplication.
# Utiliser un modèle partagé
use App\Specifics\Shares\Models\Category;
use App\Specifics\Shares\Models\Tag;
# Utiliser un concern partagé
use App\Specifics\Shares\Models\Concerns\HasComments;
class Example extends Model
{
use HasComments;
// ...
}
Bonnes pratiques
Séparation des responsabilités
- • Actions : Logique métier simple et atomique
- • Services : Orchestration de plusieurs actions
- • Queries : Récupération de données complexes
- • Controllers/Livewire : Gestion des requêtes HTTP
Réutilisation via Shares
- • Utiliser les modèles partagés (Category, Tag, Comment, etc.)
- • Utiliser les concerns (HasComments, HasReactions, etc.)
- • Utiliser les enums partagés (CategoryType, TagType, etc.)
- • Éviter la duplication de code entre modules
Transactions et événements
- • Utiliser
DB::transaction()dans les Actions - • Déclencher des événements après les actions importantes
- • Utiliser les Listeners pour les effets de bord (notifications, logs)
Validation et autorisation
- • Toujours utiliser des FormRequest pour la validation
- • Créer des Policies pour l'autorisation
- • Vérifier les permissions dans les Actions si nécessaire
Exemple complet : Flux de création
Exemple : Création d'un feedback
1. Route (routes/web.php) :
Route::get('/feedback/create', Create::class)
->middleware('auth')
->name('feedback.create');
2. Composant Livewire (app/Livewire/FeedbackHub/Feedback/Create.php) :
public function save(CreateFeedbackAction $action)
{
$this->validate();
$feedback = $action->execute(auth()->user(), [
'type' => FeedbackType::from($this->type),
'title' => $this->title,
'description' => $this->description,
]);
return redirect()->route('feedback.show', $feedback);
}
3. Action (app/Specifics/FeedbackHub/Actions/CreateFeedbackAction.php) :
public function execute(User $user, array $data): Feedback
{
return DB::transaction(function () use ($user, $data) {
$feedback = Feedback::create([
'user_id' => $user->id,
'status' => FeedbackStatus::OPEN,
...$data,
]);
event(new FeedbackCreated($feedback));
return $feedback;
});
}
4. Listener (app/Specifics/FeedbackHub/Listeners/SendFeedbackNotification.php) :
public function handle(FeedbackCreated $event)
{
// Envoyer une notification aux admins
CreateNotificationAction::execute(...);
}
Ressources supplémentaires
Prêt à développer ?
Suivez ces modes opératoires pour créer de nouvelles fonctionnalités de manière cohérente et maintenable. N'hésitez pas à consulter les modules existants comme référence.