
Optimiser les performances Laravel : Astuces simples pour améliorer votre application
Introduction
La performance est cruciale pour offrir une expérience utilisateur optimale dans vos applications Laravel. Dans cet article, nous explorerons plusieurs optimisations simples mais efficaces : Eager Loading vs Lazy Loading, l'utilisation de select() pour cibler les colonnes nécessaires, l'indexation des bases de données, et la gestion de la logique dans les modèles. Ces techniques vous aideront à rendre votre application plus rapide, plus légère et plus scalable.
1. Eager Loading vs Lazy Loading : optimiser les requêtes Eloquent
L'une des optimisations les plus simples et efficaces dans Laravel consiste à bien gérer le chargement des relations avec Eloquent. Par défaut, Laravel utilise le lazy loading, c’est-à-dire qu’il charge les relations uniquement lorsqu’on y accède. Cela peut entraîner une avalanche de requêtes SQL, surtout lorsqu’on itère sur une collection de modèles ayant des relations.
Prenons un exemple :
$posts = Post::all(); foreach ($posts as $post) { echo $post->author->name; }
Ici, si vous avez 100 articles, Laravel exécutera 1 requête pour récupérer les posts… puis 100 requêtes supplémentaires pour récupérer les auteurs, soit 101 requêtes au total !
Pour éviter cela, on utilise l’eager loading avec la méthode with():
$posts = Post::with('author')->get(); foreach ($posts as $post) { echo $post->author->name; }
Dans ce cas, Laravel exécute seulement 2 requêtes : une pour les posts, et une pour tous les auteurs liés. Le gain en performance est significatif, surtout sur des projets de grande taille.
Bon réflexe à adopter : quand vous accédez à une relation dans une boucle, pensez à l’eager loading pour éviter le N+1 problem.
❌ Mauvaise pratique : tout charger avec all():
$users = User::all(); foreach ($users as $user) { echo $user->email . "\n"; }
Cette méthode peut fonctionner pour quelques centaines d’utilisateurs, mais pas pour des milliers ou des millions.
✅ Bonne pratique : utiliser lazy()
$users = User::lazy(); foreach ($users as $user) { echo $user->email . "\n"; }
lazy() lit les données par lots (batches) (généralement de 1000), ce qui permet une meilleure gestion de la mémoire. C’est idéal pour les traitements en arrière-plan ou les scripts artisan.
🔄 Alternative: cursor()
$users = User::cursor(); foreach ($users as $user) { echo $user->email . "\n"; }
cursor() fonctionne de manière similaire à lazy() mais il utilise un curseur de base de données, ce qui signifie que Laravel ne garde rien en mémoire du tout. Chaque enregistrement est lu un par un, ce qui en fait l’option la plus économe en mémoire, mais aussi un peu plus lente que lazy() en général.
🎯 En résumé :
• Utilisez lazy() pour un bon compromis entre performance et mémoire.
• Utilisez cursor() si vous avez besoin du minimum d’utilisation mémoire, au prix d’une légère baisse de vitesse.
• Évitez all() pour des jeux de données massifs.
3. Utiliser le cache Laravel pour booster les performances
Laravel propose plusieurs mécanismes de mise en cache qui permettent d’éviter les traitements inutiles à chaque requête. Bien utilisés, ils peuvent réduire considérablement le temps de chargement de vos pages.
🚀config:cache – Cache des fichiers de configuration
Lorsqu’une application Laravel démarre, elle charge tous les fichiers du dossier config. En production, ce chargement peut être centralisé et optimisé avec :
php artisan config:cache
Cette commande génère un seul fichier contenant toutes les configurations, permettant un chargement plus rapide.
⚠️ Attention : après avoir exécuté cette commande, toute modification dans les fichiers de configuration n’aura plus d’effet tant que vous ne relancez pas la commande.
🧭 route:cache – Cache des routes
Laravel peut aussi compiler toutes vos routes non anonymes dans un fichier unique pour améliorer leur chargement :
php artisan route:cache
Cela accélère considérablement les performances des applications avec beaucoup de routes.
💡 Conseil : utilisez uniquement route:cache en production, car les routes de type Closure ne sont pas compatibles avec cette commande.
📦 view:cache – Précompiler les vues Blade
Laravel compile déjà automatiquement les vues Blade, mais on peut forcer leur compilation avec :
php artisan view:cache
Cela évite à Laravel de les recompiler à chaque première visite après un déploiement.
✅ Bonnes pratiques :
- Automatisez ces commandes dans votre pipeline de déploiement.
- Utilisez également php artisan optimize ou php artisan optimize:clear pour gérer les caches en développement.
- Pensez à utiliser php artisan config:clear, route:clear, view:clear quand vous faites des modifications locales.
4. Indexer correctement la base de données pour accélérer les requêtes
Lorsqu’on travaille avec une application Laravel connectée à une base de données, il est essentiel d’optimiser les performances à la source : au niveau du schéma de la base de données. L’une des façons les plus efficaces d’y parvenir est d’utiliser des index.
📌 Qu’est-ce qu’un index en base de données ?
Un index est une structure de données qui permet à la base de données de retrouver rapidement les lignes correspondant à une condition. Sans index, MySQL (ou autre moteur) doit effectuer un scan complet de la table, ce qui devient très lent dès que le volume augmente.
Prenons un exemple avec une table users :
$users = User::where('email', $email)->first();
Si la colonne email n’est pas indexée, la base de données doit parcourir chaque ligne jusqu’à trouver la bonne. Mais si vous avez ajouté un index sur email, la recherche devient quasi instantanée, même avec des millions de lignes.
🛠 Ajouter un index avec une migration Laravel
Vous pouvez facilement ajouter un index dans une migration :
Schema::table('users', function (Blueprint $table) { $table->index('email'); });
Il existe plusieurs types d’index :
- index() : index standard
- unique() : index unique (utile pour email, username, etc.)
- primary() : index de clé primaire
💡 Conseil : indexez les colonnes utilisées dans les clauses WHERE, ORDER BY, ou JOIN.
⚠️ Attention aux excès
Trop d’index peut aussi ralentir les opérations d’écriture (insertion, mise à jour), car la base doit maintenir tous ces index. L’indexation doit donc être réfléchie et ciblée.
5. Ne récupérer que les colonnes nécessaires avec select()
Par défaut, lorsque vous utilisez une requête Eloquent comme :
$users = User::all();
Laravel exécute la requête SQL suivante :
SELECT * FROM users;
Cela signifie que toutes les colonnes de la table users sont récupérées, même si vous n’en avez besoin que d’une ou deux dans votre traitement. Sur de grandes tables avec beaucoup de colonnes ou d’enregistrements, cela peut alourdir inutilement la mémoire et ralentir vos traitements.
✅ Bonne pratique : cibler les colonnes
Lorsque vous savez exactement de quelles colonnes vous avez besoin, utilisez select() pour réduire la charge de la requête :
$users = User::select('name', 'email')->get();
Laravel générera alors une requête SQL plus légère :
SELECT name, email FROM users;
Cela permet :
- de réduire la quantité de données transférées entre la base et l’application,
- de consommer moins de mémoire,
- et d’accélérer l’exécution globale.
📌 Exemple avec une condition
$activeUsers = User::select('id', 'name') ->where('is_active', true) ->get();
Vous récupérez ici uniquement les champs nécessaires pour vos traitements. C’est aussi utile si vous passez les données à une API ou une vue, cela évite de transporter des données sensibles comme les mots de passe, tokens, etc.
🔐 Sécurité bonus : n’exposez pas de colonnes sensibles par inadvertance (password, rember_token, etc.)
✅ À retenir :
• Toujours utiliser select() pour optimiser vos requêtes.
• Plus votre table contient de colonnes, plus l’impact sera important.
• Cela contribue à une application plus rapide, légère et plus sûre.
6. Optimiser les vues en déplaçant la logique dans le modèle
Une bonne pratique de design MVC est de déplacer toute la logique métier du côté des modèles et de garder les vues aussi simples que possible. Cela permet de maintenir une architecture propre, de rendre le code plus lisible, et de centraliser la logique de traitement des données dans les modèles plutôt que dans les vues.
❌ Mauvaise pratique : logique dans la vue
Regardons cet exemple où la logique est directement dans la vue :
@foreach ($posts as $post) @if (strlen($post->title) > 50) <h3>{{ substr($post->title, 0, 50) }}..</h3> @else <h3>{{ $post->title }}</h3> @endif @endforeach
Dans ce cas, la vue contient une logique de traitement de chaîne, ce qui n'est pas optimal et enfreint le principe de séparation des préoccupations (le modèle doit gérer les données, pas la vue).
✅ Optimisation : déplacer la logique dans le modèle
Au lieu de cela, nous allons créer une méthode dans le modèle Post, qui sera responsable de cette logique. Par exemple, une méthode getOptimizedTitle() :
// Dans le modèle Post class Post extends Model { public function getOptimizedTitle() { return strlen($this->title) > 50 ? substr($this->title, 0, 50) . '...' : $this->title; } }
Maintenant, dans la vue, vous n’avez plus qu’à appeler cette méthode pour afficher le titre optimisé :
@foreach ($posts as $post) <h3>{{ $post->getOptimizedTitle() }}</h3> @endforeach
Cette solution permet de :
- Garder la logique métier dans le modèle, là où elle appartient.
- Simplifier les vues et les rendre plus lisibles.
- Faciliter la réutilisation de la logique dans d'autres parties de l'application.
✅ À retenir :
• Déplacez toute logique métier dans le modèle pour garder les vues simples et lisibles.
• Cela permet de maintenir une bonne séparation des responsabilités et de centraliser le traitement des données.
• Profitez des méthodes de modèle pour rendre votre code plus modulaire et réutilisable.
7. Utiliser le cache pour améliorer les performances des requêtes fréquemment exécutées
Le caching est une technique très puissante pour améliorer les performances de ton application Laravel. Si tu as des requêtes qui sont exécutées fréquemment et qui ne changent pas souvent (par exemple, récupérer une liste de catégories ou un nombre d'utilisateurs), il peut être judicieux de les mettre en cache.
Exemple avec Cache :
Laravel offre une API de cache simple à utiliser. Tu peux facilement mettre en cache les résultats d’une requête :
$users = Cache::remember('users_list', 60, function () { return User::all(); });
Ici, la liste des utilisateurs sera stockée dans le cache pendant 60 minutes. Après ce délai, Laravel exécutera de nouveau la requête et mettra à jour le cache.
Cela permet de réduire la charge sur la base de données, en servant des données directement depuis le cache au lieu de faire des requêtes répétées.
💡 Astuce : Utilise un cache spécifique comme Cache::rememberForever() pour les données qui ne changent jamais, comme des configurations statiques ou des données partagées entre plusieurs sessions utilisateurs.
Conclusion
Optimiser les performances de vos applications Laravel ne nécessite pas toujours des changements radicaux. En appliquant quelques bonnes pratiques comme l'Eager Loading, l'utilisation de select() pour cibler les colonnes nécessaires, ou encore la gestion de la logique dans les modèles, vous pouvez considérablement améliorer la réactivité et l'efficacité de votre code. Ces optimisations simples et efficaces permettent de garantir une meilleure expérience utilisateur tout en assurant une maintenance plus facile et une scalabilité accrue.
En résumé, chaque petit ajustement compte et peut faire une grande différence. Adopter ces bonnes pratiques dès le début de votre projet vous permettra de créer des applications Laravel robustes et performantes.