Créer un nouveau module Laravel

Guide complet étape par étape pour créer un nouveau module conforme aux standards et conventions du projet.

Version 1.0 Dernière mise à jour : 2025-01-12

1. Vue d'ensemble

Prérequis

  • • Compréhension de Laravel
  • • Connaissance des patterns
  • • Environnement configuré

Temps estimé

  • • Module simple : 30-45 min
  • • Module moyen : 1-2 heures
  • • Module complexe : 2-4 heures

Structure finale

Dossiers standardisés : Actions, Queries, Models, Policies, Enums, Events, etc.

2. Structure d'un module

app/Specifics/ModuleName/
├── Actions/              # Actions métier atomiques
├── Commands/             # Commandes Artisan (optionnel)
├── Controllers/          # Contrôleurs HTTP (optionnel)
├── DTO/                  # Data Transfer Objects (optionnel)
├── Enums/                # Énumérations
├── Events/               # Événements
├── Factories/            # Factories pour tests
├── Listeners/            # Écouteurs d'événements (optionnel)
├── Models/               # Modèles Eloquent
├── Observers/            # Observers Eloquent (optionnel)
├── Policies/             # Policies d'autorisation
├── Queries/              # Queries pour récupération de données
├── Requests/             # Form Requests (optionnel)
└── Services/             # Services métier complexes (optionnel)

3. Étapes de création

Étape 1 : Planification

Avant de commencer, définissez :

  • Nom du module : PascalCase, singulier (ex: Product, Order)
  • Entité principale : Le modèle principal
  • Fonctionnalités : Liste des fonctionnalités à implémenter
  • Dépendances : Modules dont dépend ce module

Étape 2 : Créer la structure de base

Créer les dossiers :

# Depuis la racine du projet
mkdir -p app/Specifics/Products/{Actions,Commands,Controllers,DTO,Enums,Events,Factories,Listeners,Models,Observers,Policies,Queries,Requests,Services}

# Créer les fichiers .gitkeep dans les dossiers vides
touch app/Specifics/Products/{Commands,Controllers,DTO,Listeners,Observers,Requests,Services}/.gitkeep

Ou utiliser la commande Artisan :

php artisan make:module Products

Étape 3 : Créer le modèle principal

Fichier : app/Specifics/Products/Models/Product.php

namespace App\Specifics\Products\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;

class Product extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'name',
        'description',
        'price',
        'status',
        'user_id',
    ];

    protected function casts(): array
    {
        return [
            'price' => 'decimal:2',
            'status' => ProductStatus::class,
        ];
    }

    protected static function newFactory()
    {
        return ProductFactory::new();
    }
}

Étape 4 : Créer la migration

php artisan make:migration create_products_table

Étape 5 : Créer les Enums

Fichier : app/Specifics/Products/Enums/ProductStatus.php

enum ProductStatus: string
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';

    public function label(): string
    {
        return match ($this) {
            self::DRAFT => 'Brouillon',
            self::PUBLISHED => 'Publié',
            self::ARCHIVED => 'Archivé',
        };
    }

    public function color(): string
    {
        return match ($this) {
            self::DRAFT => 'gray',
            self::PUBLISHED => 'success',
            self::ARCHIVED => 'warning',
        };
    }
}

Étape 6 : Créer les Actions

Utiliser la commande Artisan :

php artisan make:action Products CreateProductAction
php artisan make:action Products UpdateProductAction
php artisan make:action Products DeleteProductAction

Exemple d'Action :

class CreateProductAction
{
    public function execute(User $user, array $data): Product
    {
        $data['user_id'] = $user->id;

        return DB::transaction(function () use ($data) {
            $product = Product::create($data);
            event(new ProductCreated($product));
            return $product;
        });
    }
}

Étape 7 : Créer les Queries

Utiliser la commande Artisan :

php artisan make:query Products GetProductListQuery
php artisan make:query Products GetProductDetailQuery

Exemple de Query :

class GetProductListQuery
{
    public function execute(
        ?ProductStatus $status = null,
        ?string $search = null,
        int $perPage = 15
    ): LengthAwarePaginator {
        $query = Product::with(['user']);

        if ($status) {
            $query->where('status', $status);
        }

        return $query->orderBy('created_at', 'desc')
            ->paginate($perPage);
    }
}

Étape 8 : Créer les Policies

Fichier : app/Specifics/Products/Policies/ProductPolicy.php

class ProductPolicy
{
    public function viewAny(User $user): bool
    {
        return $user->hasPermissionTo('view-products');
    }

    public function create(User $user): bool
    {
        return $user->hasPermissionTo('create-products');
    }

    public function update(User $user, Product $product): bool
    {
        return $user->hasPermissionTo('update-products')
            || ($product->user_id === $user->id
                && $user->hasPermissionTo('update-own-products'));
    }
}

Enregistrer dans app/Providers/AuthServiceProvider.php

4. Commandes Make personnalisées

make:action

Génère une nouvelle classe Action pour un module spécifique.

php artisan make:action {module} {name}

# Exemples
php artisan make:action Products CreateProductAction
php artisan make:action FeedbackHub UpdateFeedbackStatusAction

✅ Génère automatiquement le namespace correct
✅ Extrait l'entité du nom de l'Action
✅ Ajoute automatiquement le suffixe "Action" si manquant

make:query

Génère une nouvelle classe Query pour un module spécifique.

php artisan make:query {module} {name}

# Exemples
php artisan make:query Products GetProductListQuery
php artisan make:query FeedbackHub GetFeedbackDetailQuery

✅ Génère automatiquement le namespace correct
✅ Ajoute automatiquement le préfixe "Get" et suffixe "Query" si manquants

make:service

Génère une nouvelle classe Service pour un module spécifique.

php artisan make:service {module} {name}

# Exemples
php artisan make:service Products ProductService
php artisan make:service Email ContactSyncService

✅ Génère automatiquement le namespace correct
✅ Injection de dépendances configurée
✅ Méthodes de base générées

make:module

Génère un module complet avec toute sa structure de dossiers et fichiers de base.

php artisan make:module {name} {entity?}

# Exemples
php artisan make:module Products Product
php artisan make:module Orders

✅ Génère toute la structure de dossiers standardisée
✅ Crée les fichiers de base (Model, Enum, Policy, Factory)
✅ Ajoute les fichiers .gitkeep dans les dossiers optionnels

make:dto

Génère une nouvelle classe DTO pour un module spécifique.

php artisan make:dto {module} {name}

# Exemples
php artisan make:dto Products CreateProductData
php artisan make:dto FeedbackHub UpdateFeedbackData

✅ Propriétés readonly pour l'immutabilité
✅ Méthodes toArray() et fromArray() incluses

make:filament-resource

Génère une Resource Filament complète avec Pages, Schemas et Tables.

php artisan make:filament-resource {module} {entity} [--panel=admin]

# Exemples
php artisan make:filament-resource FeedbackHub Feedback --panel=admin
php artisan make:filament-resource Products Product --panel=app

✅ Génère toute la structure Filament
✅ Crée les 3 Pages (List, Create, Edit)
✅ Crée le Schema et la Table

5. Checklist de validation

Structure

  • Tous les dossiers requis sont créés
  • Fichiers .gitkeep dans les dossiers vides
  • Structure conforme à l'architecture

Modèle

  • Modèle créé avec namespace correct
  • Factory créée et enregistrée
  • Migration créée et exécutée

Actions & Queries

  • Actions créées avec namespace correct
  • Queries créées avec eager loading
  • Transactions DB utilisées

Policies & Tests

  • Policy créée et enregistrée
  • Tests créés pour les Actions
  • Tous les tests passent

6. Exemples de modules de référence

Module simple : Blog

Structure claire et minimale, bon exemple pour commencer.

  • • app/Specifics/Blog/Models/Post.php
  • • app/Specifics/Blog/Actions/CreatePostAction.php
  • • app/Specifics/Blog/Queries/GetPublishedPostsQuery.php

Module complet : FeedbackHub

Structure très complète, tous les patterns utilisés.

  • • app/Specifics/FeedbackHub/Models/Feedback.php
  • • app/Specifics/FeedbackHub/Actions/CreateFeedbackAction.php
  • • app/Specifics/FeedbackHub/Queries/GetFeedbackListQuery.php

Module avec DTO : Realtime

Utilisation de DTOs, bon exemple d'architecture.

  • • app/Specifics/Realtime/DTO/CreateRoomData.php
  • • app/Specifics/Realtime/Actions/CreateChatRoomAction.php

7. FAQ

Dois-je créer tous les dossiers ?

Non, créez seulement les dossiers nécessaires. Les dossiers minimaux sont : Models/, Enums/, Policies/, Actions/ et Queries/.

Quand utiliser un Service ?

Utilisez un Service quand vous devez orchestrer plusieurs Actions/Queries, quand la logique métier est complexe, ou quand vous avez des intégrations externes multiples.

Quand utiliser un DTO ?

Utilisez un DTO quand vous avez des données complexes à passer entre couches, quand vous voulez garantir la structure des données, ou quand vous avez besoin de validation centralisée.

Comment tester mon module ?

Créez les tests dans tests/Feature/Specifics/{ModuleName}/, utilisez les factories pour créer les données de test, et exécutez : php artisan test --filter={ModuleName}

8. Commandes utiles

# Créer un module complet
php artisan make:module Products

# Créer une migration
php artisan make:migration create_products_table

# Créer une factory
php artisan make:factory ProductFactory --model=App\\Specifics\\Products\\Models\\Product

# Exécuter les migrations
php artisan migrate

# Exécuter les tests
php artisan test --filter=Products

# Formater le code
./vendor/bin/pint app/Specifics/Products/

Support

En cas de question ou problème :

  • Consultez les modules de référence (Blog, FeedbackHub)
  • Vérifiez la documentation de l'architecture
  • Contactez l'équipe de développement

Prendre rendez-vous