Blog & Actualités
Ajoutez une section blog et actualités complète à votre site Larapen. Créez des articles avec catégories, tags, images à la une et un système de commentaires imbriqués avec modération : le tout entièrement traduisible.
Éditeur d'articles enrichi
Créez des articles avec des titres, slugs, contenus, extraits et métadonnées SEO traduisibles. Associez des images à la une via la médiathèque.
Catégories & Tags
Organisez le contenu avec des catégories hiérarchiques (utilisant la table unifiée des catégories) et un système de tags flexible.
Commentaires imbriqués
Réponses de commentaires imbriquées avec profondeur configurable, file de modération, approbation automatique pour les commentateurs de confiance et support CAPTCHA.
Multi-langue
Tous les articles, catégories et tags supportent les traductions via Spatie Translatable. URLs front-end localisées avec préfixe de langue.
Notifications par e-mail
Les administrateurs sont notifiés des nouveaux commentaires. Les auteurs de commentaires sont notifiés lorsque quelqu'un répond à leur commentaire.
Temps de lecture & Vues
Calcul automatique du temps de lecture (MPM configurable) et suivi du nombre de vues pour chaque article.
Cas d'utilisation
Blog d'entreprise
Publiez des actualités d'entreprise, des mises à jour produit et des analyses sectorielles. Organisez les articles par catégorie (ex. « Mises à jour produit », « Actualités du secteur », « Tutoriels ») et laissez les visiteurs interagir via les commentaires.
Blog Portfolio
Complétez votre portfolio avec des articles en coulisses, des études de cas et des comptes-rendus de projets. Taguez les articles avec les noms de projets ou technologies pertinents pour faciliter les références croisées.
Hub de contenu multilingue
Publiez des articles en plusieurs langues (anglais, français, etc.) avec des slugs et contenus par langue. Chaque article peut avoir des traductions entièrement indépendantes gérées depuis le panneau d'administration.
Section Actualités
Utilisez le blog comme section presse/actualités. Exploitez la date de publication pour la planification et le workflow « brouillon/publié » pour le contrôle éditorial.
Prérequis
- Larapen CMS v1.0.0 ou ultérieur
- PHP 8.3+
- MySQL 8.0+ (requis pour
JSON_SEARCHdans les recherches de slugs traduisibles) - La table categories du noyau doit exister (les catégories du blog utilisent la table unifiée
categoriesaveccategorizable_type = 'post')
Installation
Étape 1 : Placer l'add-on
Copiez ou créez un lien symbolique du dossier blog dans le répertoire « extensions/addons » de votre Larapen :
Étape 2 : Activer l'add-on
Allez dans Admin → Add-ons → Add-ons installés et activez Blog & Actualités.
Étape 3 : Exécuter les migrations
Cela crée 4 tables : blog_posts, blog_post_tags, blog_post_tag (pivot),
et blog_comments. Les catégories du blog utilisent la table categories existante du noyau.
Étape 4 : Définir les permissions
L'add-on enregistre 16 permissions (voir Permissions). Attribuez-les aux rôles admin via Admin → Utilisateurs → Rôles & Permissions.
Étape 5 : Configurer
Allez dans Admin → Blog → Paramètres pour configurer le nombre d'articles par page, les règles de modération des commentaires, les notifications et les paramètres de temps de lecture. Voir Paramètres.
Étape 6 : Exécuter le build Vite (si vous utilisez des thèmes)
Nécessaire si de nouveaux fichiers SCSS/JS ont été ajoutés aux répertoires de thèmes pour les pages du blog.
Configuration
L'add-on blog est livré avec un fichier de configuration config/blog.php qui définit les valeurs par défaut.
Tous les paramètres peuvent être modifiés depuis le panneau d'administration (stockés dans la table settings, groupe blog).
| Paramètre | Description | Défaut |
|---|---|---|
blog_posts_per_page |
Nombre d'articles affichés par page sur la liste du blog. | 10 |
blog_related_posts_count |
Nombre d'articles associés affichés en bas de chaque page de détail d'article. | 3 |
blog_words_per_minute |
Vitesse de lecture moyenne utilisée pour calculer l'estimation « X min de lecture ». | 200 |
blog_comments_enabled |
Activer ou désactiver le système de commentaires globalement. | true |
blog_comments_require_approval |
Lorsque activé, les commentaires des visiteurs doivent être approuvés par un admin avant d'apparaître. Les commentaires des utilisateurs authentifiés sont approuvés automatiquement. | true |
blog_allow_guest_comments |
Autoriser les visiteurs non connectés à laisser des commentaires (nécessite nom et e-mail). | false |
blog_comments_max_depth |
Niveau d'imbrication maximum pour les réponses de commentaires (1–5). | 2 |
blog_auto_approve_trusted_commenters |
Approuver automatiquement les commentaires des utilisateurs qui ont déjà un commentaire approuvé (correspondance par e-mail). | false |
blog_notify_admin_on_comment |
Envoyer des notifications par e-mail à tous les administrateurs lorsqu'un nouveau commentaire ou une réponse est posté(e). | true |
blog_notify_author_on_reply |
Envoyer des notifications par e-mail aux auteurs de commentaires lorsque quelqu'un répond à leur commentaire. | true |
blog_captcha_enabled |
Exiger une vérification CAPTCHA lors de la publication de commentaires (nécessite qu'un fournisseur CAPTCHA soit configuré dans les paramètres du noyau). | false |
Valeurs par défaut du fichier de configuration
Le fichier config/blog.php inclut également les dimensions des images à la une utilisées lors du traitement des uploads :
| Clé | Description | Défaut |
|---|---|---|
featured_images.width |
Largeur de l'image à la une (px) | 1200 |
featured_images.height |
Hauteur de l'image à la une (px) | 630 |
featured_images.thumbnail_width |
Largeur de la miniature (px) | 400 |
featured_images.thumbnail_height |
Hauteur de la miniature (px) | 250 |
Admin : Articles
La page Articles (Blog → Tous les articles) est l'interface principale pour gérer le contenu du blog.
Liste des articles
Un tableau trié et paginé (20 par page) affichant :
- Image à la une en miniature
- Titre (traduisible)
- Catégorie
- Auteur
- Statut (Brouillon / Publié)
- Nombre de vues
- Nombre de commentaires
- Date de publication
Filtres & Recherche
La liste des articles supporte trois dimensions de filtrage :
- Recherche : recherche dans les titres des articles (dans toutes les langues traduites via
JSON_SEARCH) - Statut : filtrer par
draftoupublished - Catégorie : filtrer par une catégorie spécifique
Création & Édition d'articles
Le formulaire d'article comprend les champs suivants, chacun supportant les traductions par langue :
Champs de contenu (par langue)
| Champ | Validation | Notes |
|---|---|---|
title |
Requis (langue par défaut), max 255 | Traduisible. Utilisé pour générer automatiquement le slug. |
slug |
Optionnel, max 255 | Traduisible. Généré automatiquement à partir du titre si laissé vide. |
content |
Optionnel | Traduisible. Contenu de l'éditeur WYSIWYG. |
excerpt |
Optionnel, max 500 | Traduisible. Court résumé pour les pages de liste. |
meta_title |
Optionnel, max 70 | Traduisible. Balise titre SEO. |
meta_description |
Optionnel, max 160 | Traduisible. Méta description SEO. |
Champs non traduisibles
| Champ | Validation | Notes |
|---|---|---|
category_id |
Optionnel, doit exister dans categories |
Catégorie du blog (depuis la table unifiée des catégories) |
featured_image |
Optionnel, fichier image | Téléchargé via le service média du noyau |
status |
Requis, draft ou published |
Utilise l'enum PageStatus |
published_at |
Optionnel, date | Défini automatiquement à l'heure actuelle lors de la première publication si vide |
tags |
Optionnel, tableau d'IDs de tags | Sélection multiple parmi les tags existants |
Str::slug().
Admin : Catégories
Les catégories du blog (Blog → Catégories) utilisent la table unifiée categories du noyau,
filtrée par categorizable_type = 'post'. Cela signifie qu'elles partagent la même structure de table que
les catégories de portfolio et d'autres add-ons, mais sont isolées via un scope global sur le modèle PostCategory.
Champs de catégorie
| Champ | Notes |
|---|---|
name |
Traduisible. Requis pour la langue par défaut. |
slug |
Traduisible. Généré automatiquement à partir du nom si vide. |
description |
Traduisible. Optionnel. |
parent_id |
Nullable. Supporte un niveau d'imbrication (parent → enfant). |
position |
Entier pour le tri manuel. |
is_active |
Booléen. Les catégories inactives sont masquées du front-end. |
Admin : Tags
Les tags (Blog → Tags) sont des étiquettes légères pouvant être associées à n'importe quel article.
Contrairement aux catégories, les tags sont plats (pas de hiérarchie) et sont stockés dans la table blog_post_tags.
Champs de tag
| Champ | Notes |
|---|---|
name |
Traduisible. Le nom d'affichage du tag. |
slug |
Traduisible. Identifiant compatible URL. |
La liste des tags affiche chaque tag avec son nombre d'articles associés. Les tags sont recherchables par nom et paginés (20 par page).
detach()), mais les articles eux-mêmes ne sont pas affectés.
Admin : Commentaires
La page Commentaires (Blog → Commentaires) fournit une interface de modération pour tous les commentaires du blog à travers tous les articles.
Liste des commentaires
Un tableau paginé (20 par page) affichant :
- Auteur : nom de l'utilisateur (si authentifié) ou nom/e-mail du visiteur
- Contenu : aperçu du texte du commentaire
- Article : l'article de blog auquel appartient le commentaire
- Statut : badge Approuvé / En attente
- Date
Un badge de compteur en attente est affiché dans l'en-tête pour identifier rapidement les éléments nécessitant une attention.
Modération
Actions par commentaire :
- Voir : voir le contenu complet du commentaire, les réponses et le contexte de l'article
- Approuver (
PATCH) : marque le commentaire comme approuvé - Supprimer : supprime définitivement le commentaire
Filtrer par statut
Utilisez le paramètre de requête status pour filtrer :
?status=pending: afficher uniquement les commentaires en attente (non approuvés)?status=approved: afficher uniquement les commentaires approuvés
Actions groupées
Sélectionnez plusieurs commentaires à l'aide des cases à cocher et appliquez des actions groupées :
- Approuver : approuver tous les commentaires sélectionnés en une fois
- Supprimer : supprimer tous les commentaires sélectionnés
Les actions groupées sont envoyées en POST admin/blog/comments/bulk avec action et
les ids séparés par des virgules.
Admin : Paramètres
La page des paramètres (Blog → Paramètres) est organisée en quatre sections :
Affichage des articles
- Articles par page : nombre d'articles sur la page de liste (1–100)
- Articles associés : nombre d'articles associés affichés sur les pages de détail (0–12)
- Mots par minute : vitesse de lecture pour le calcul du temps de lecture (100–500)
Commentaires
- Activer les commentaires : interrupteur global pour le système de commentaires
- Approbation requise : si les commentaires des visiteurs nécessitent l'approbation de l'admin (les utilisateurs authentifiés sont toujours approuvés automatiquement)
- Commentaires des visiteurs : autoriser les visiteurs non connectés à commenter
- Profondeur des réponses : niveau d'imbrication maximum pour les réponses (1–5)
- Approbation automatique des commentateurs de confiance : approuver automatiquement les commentaires des e-mails qui ont déjà un commentaire approuvé
Notifications
- Notification admin : envoyer un e-mail aux admins lorsqu'un nouveau commentaire/réponse est posté(e)
- Notification de réponse : envoyer un e-mail aux auteurs de commentaires lorsque quelqu'un répond à leur commentaire
Protection CAPTCHA
- Activer le CAPTCHA pour les commentaires : exiger une vérification CAPTCHA lors de la publication de commentaires
Nécessite qu'un fournisseur CAPTCHA soit configuré dans les paramètres du noyau. Si aucun fournisseur n'est configuré, un avertissement est affiché avec un lien vers la page de configuration.
Front-end : Liste du blog
La page de liste du blog (/{locale}/blog) affiche les articles publiés avec pagination.
Contenu principal
- Cartes d'articles : chacune affichant : miniature de l'image à la une, titre, extrait, badge de catégorie, nom de l'auteur, date de publication, temps de lecture et nombre de vues
- Pagination : nombre d'articles par page configurable
Barre latérale
- Catégories : liste des catégories actives avec le nombre d'articles
- Articles récents : les 5 articles les plus récemment publiés
- Articles populaires : les 5 articles les plus vus
- Tags : tous les tags qui ont au moins un article
Front-end : Détail de l'article
La page de détail de l'article (/{locale}/blog/{slug}) affiche le contenu complet de l'article.
Contenu
- En-tête : titre, catégorie, auteur, date de publication, temps de lecture, nombre de vues
- Image à la une : image hero pleine largeur (via relation média polymorphique)
- Corps du contenu : contenu HTML rendu
- Tags : badges de tags liés aux pages de filtre par tag
- Navigation entre articles : liens vers l'article précédent / suivant
- Articles associés : articles partageant la même catégorie ou les mêmes tags (nombre configurable)
- Section commentaires : commentaires imbriqués avec formulaire de réponse (voir Commentaires)
Suivi du nombre de vues
À chaque chargement de la page de détail, PostService::incrementViewCount()
incrémente la colonne view_count. Cela alimente le widget « Articles populaires » de la barre latérale.
Algorithme des articles associés
Les articles associés sont sélectionnés par correspondance :
- Articles dans la même catégorie
- Articles partageant les mêmes tags
Les résultats sont triés par date de publication (le plus récent en premier) et limités au nombre configuré.
Front-end : Pages Catégorie & Tag
Page Catégorie
URL : /{locale}/blog/category/{slug}
Affiche tous les articles publiés dans la catégorie spécifiée avec la même pagination, les mêmes widgets de barre latérale et la même mise en page des cartes d'articles que la liste principale. La catégorie est résolue par son slug traduisible (langue actuelle en premier, puis repli sur l'anglais).
Page Tag
URL : /{locale}/blog/tag/{slug}
Affiche tous les articles publiés taggués avec le tag spécifié. Même mise en page que la page catégorie. Le tag est résolu par son slug traduisible.
Front-end : Recherche
URL : /{locale}/blog/search?q={query}
Recherche plein texte dans les titres et contenus des articles dans toutes les langues via MySQL JSON_SEARCH.
Les résultats sont paginés et affichés avec la mise en page standard du blog.
Front-end : Commentaires
Le système de commentaires apparaît en bas de chaque page de détail d'article (lorsqu'il est activé).
Formulaire de commentaire
- Utilisateurs authentifiés : n'ont besoin de saisir que le contenu du commentaire. Approuvé automatiquement sauf si des règles de modération s'appliquent.
- Visiteurs (si activé) : doivent fournir nom, e-mail et contenu. Soumis à la modération d'approbation.
- Formulaire de réponse : des formulaires de réponse en ligne apparaissent lorsqu'on clique sur « Répondre » sur un commentaire existant, jusqu'à la profondeur maximale configurée.
- Notification de réponse : case à cocher pour activer/désactiver les notifications de réponse.
- CAPTCHA : affiché lorsque le CAPTCHA est activé pour les commentaires du blog.
Affichage des commentaires
- Les commentaires sont affichés en format imbriqué (parent → réponses).
- Seuls les commentaires approuvés sont visibles par les visiteurs du front-end.
- Chaque commentaire affiche : nom de l'auteur, date, contenu et nombre de réponses.
Règles de validation
| Champ | Validation |
|---|---|
content |
Requis, 3–2000 caractères |
parent_id |
Optionnel, doit exister dans blog_comments ; vérification de profondeur appliquée |
author_name |
Requis pour les visiteurs, max 255 |
author_email |
Requis pour les visiteurs, e-mail valide, max 255 |
notify_on_reply |
Booléen optionnel |
Logique d'approbation automatique
- Si Approbation requise est désactivée → tous les commentaires sont approuvés automatiquement.
- Si le commentateur est authentifié → approuvé automatiquement.
- Si Approbation automatique des commentateurs de confiance est activée et que l'e-mail a déjà un commentaire approuvé → approuvé automatiquement.
- Sinon → en attente (nécessite l'approbation de l'admin).
Support multilingue
L'add-on blog utilise spatie/laravel-translatable pour tous les champs de contenu.
Les traductions sont stockées sous forme de colonnes JSON dans la base de données.
Champs traduisibles par modèle
| Modèle | Champs traduisibles |
|---|---|
Post |
slug, title, content, excerpt, meta_title, meta_description |
PostCategory |
slug, name, description |
PostTag |
slug, name |
Résolution des slugs
Les contrôleurs front-end résolvent les slugs en cherchant d'abord dans la langue actuelle, puis en se repliant sur l'anglais :
Images à la une
Les articles supportent une seule image à la une via une relation polymorphique MorphOne
vers le modèle Media du noyau (mediable). Le trait HasMedia est inclus dans le modèle Post.
Flux de téléchargement
- L'admin télécharge un fichier image via le formulaire de création/édition d'article.
- Le
PostServicedélègue àMediaService::uploadFor(). - L'image est stockée dans le sous-répertoire
postsdu disque média. - Les miniatures sont générées selon les dimensions de configuration (
featured_images.thumbnail_width/height).
Suppression d'image
Le formulaire d'édition inclut une case à cocher « Supprimer l'image à la une ». Lorsqu'elle est cochée,
l'enregistrement média existant et les fichiers sont supprimés via MediaService::delete().
Le téléchargement d'une nouvelle image remplace automatiquement l'ancienne.
Notifications par e-mail
L'add-on blog envoie deux types de notifications par e-mail :
Notification de nouveau commentaire
Envoyée à tous les administrateurs (is_admin = true) lorsqu'un nouveau commentaire ou une réponse est posté(e).
- Objet : « Nouveau commentaire sur {titre de l'article} » ou « Nouvelle réponse sur {titre de l'article} »
- Corps : Nom de l'auteur, titre de l'article, aperçu du contenu (200 caractères)
- Action : Lien « Modérer les commentaires » (si en attente) ou lien « Voir le commentaire » (si approuvé)
Contrôlé par : le paramètre blog_notify_admin_on_comment.
Notification de réponse à un commentaire
Envoyée à l'auteur du commentaire parent lorsque quelqu'un répond à son commentaire.
- Objet : « Nouvelle réponse à votre commentaire sur {titre de l'article} »
- Corps : Nom de l'auteur de la réponse, titre de l'article, aperçu du contenu
- Action : Lien « Voir la réponse »
Contrôlé par : le paramètre blog_notify_author_on_reply.
Les notifications de réponse respectent la préférence notify_on_reply du commentateur
et ne sont pas envoyées lorsque quelqu'un répond à son propre commentaire.
Protection CAPTCHA
Lorsque blog_captcha_enabled est défini à true, le formulaire de commentaire inclut
un défi CAPTCHA. L'add-on blog s'intègre avec le CaptchaService du noyau :
- Le service vérifie si le CAPTCHA est activé pour le contexte
blog. - Le nom de champ CAPTCHA approprié est résolu via
CaptchaService::getResponseFieldName(). - La validation utilise la classe
CaptchaRuledu noyau.
Un fournisseur CAPTCHA (ex. reCAPTCHA, hCaptcha) doit être configuré dans les paramètres du noyau pour que cette fonctionnalité fonctionne.
Mise à jour
Étape 1 : Remplacer les fichiers
Remplacez le répertoire de l'add-on par la nouvelle version.
Étape 2 : Exécuter les migrations
Étape 3 : Vider les caches
Étape 4 : Recompiler les assets
Nécessaire uniquement si la mise à jour inclut des fichiers SCSS/JS de thème nouveaux ou modifiés.
Étape 5 : Vérifier
Visitez Blog → Paramètres pour confirmer que la page des paramètres se charge correctement, puis vérifiez la page de liste du blog en front-end.
Dépannage
Les pages du blog retournent une erreur 404
- Assurez-vous que l'add-on Blog est activé dans Admin → Add-ons.
- Exécutez
php artisan route:clearpour vider le cache des routes. - Vérifiez que le
BlogServiceProviderest bien enregistré (vérifiez l'autoloaderAddonServiceProvider).
Un article affiche « Non trouvé » bien qu'il soit publié
- Vérifiez que le statut de l'article est
published(et nondraft). - Assurez-vous que
published_atest défini et dans le passé (les articles datés dans le futur ne sont pas visibles). - Vérifiez que le slug correspond à l'URL : les slugs sont spécifiques à la langue. Le système essaie d'abord la langue actuelle, puis l'anglais.
La page catégorie retourne une erreur 404
- Assurez-vous que la catégorie est active (
is_active = true). - Vérifiez que le
categorizable_typede la catégorie estpost. - Vérifiez que le slug dans l'URL correspond au slug traduisible de la catégorie pour la langue actuelle.
Les commentaires n'apparaissent pas sur les articles
- Vérifiez que
blog_comments_enabledest défini àtruedans les paramètres. - Si vous utilisez la modération, les commentaires doivent d'abord être approuvés. Vérifiez la page des commentaires admin pour les éléments en attente.
- Les commentaires des visiteurs nécessitent que
blog_allow_guest_commentssoit activé.
Le formulaire de commentaire ne s'affiche pas pour les visiteurs
- Activez
blog_allow_guest_commentsdans Blog → Paramètres. - Le
StoreCommentRequestvérifie l'autorisation : si les commentaires des visiteurs sont désactivés, la soumission du formulaire retourne une erreur 403.
Le CAPTCHA n'apparaît pas sur le formulaire de commentaire
- Assurez-vous que
blog_captcha_enabledest défini àtruedans les paramètres du blog. - Un fournisseur CAPTCHA doit être configuré dans Admin → Paramètres → CAPTCHA.
- La vérification
CaptchaService::isEnabledFor('blog')doit retournertrue.
Les notifications par e-mail ne sont pas envoyées
- Vérifiez que la messagerie est configurée correctement dans Admin → Paramètres → Mail.
- Vérifiez que les interrupteurs de notification sont activés :
blog_notify_admin_on_commentet/oublog_notify_author_on_reply. - Les notifications de réponse nécessitent que l'auteur du commentaire parent ait
notify_on_reply = true. - Les auto-réponses ne déclenchent pas de notifications (par conception).
Impossible de supprimer une catégorie : « Impossible de supprimer une catégorie contenant des articles »
L'add-on empêche la suppression des catégories qui ont des articles assignés. Réassignez les articles à une autre catégorie ou supprimez-les d'abord.
L'image à la une ne s'affiche pas
- Vérifiez que le fichier média a été téléchargé avec succès (cherchez dans la table
mediaunmediable_typecorrespondant à l'article). - Vérifiez que le lien symbolique de stockage existe :
php artisan storage:link. - Vérifiez les permissions des fichiers sur le répertoire de stockage.
La recherche ne retourne aucun résultat malgré des articles correspondants
- La recherche utilise MySQL
JSON_SEARCHqui nécessite MySQL 8.0+. - La recherche est par correspondance de motif (contient), donc les correspondances partielles devraient fonctionner.
- Seuls les articles publiés (avec
published_atdans le passé) sont inclus dans les résultats de recherche.
Le temps de lecture affiche « 1 min » pour tous les articles
- Assurez-vous que l'article a du contenu (le temps de lecture est calculé à partir de
strip_tags(content)). - Vérifiez le paramètre
blog_words_per_minute: la valeur par défaut est 200 MPM. - Les articles très courts afficheront toujours 1 minute (le minimum).