Page Builder
Le Page Builder permet de construire des contenus structurés à base de blocs réordonnables, traduisibles et configurables. Chaque type de bloc a son propre rendu et ses propres options.
Utilisation dans le cockpit
Lorsqu’une ressource utilise le Page Builder, l’édition du contenu se fait via une interface dédiée :
- Ajouter un bloc : cliquez sur le bouton
+pour insérer un nouveau bloc à l’endroit voulu. - Réorganiser : faites glisser un bloc pour modifier sa position.
- Configurer : l’icône engrenage de chaque bloc ouvre ses paramètres (niveau de titre, format vidéo, colonnes, etc.).
- Supprimer : la corbeille retire définitivement le bloc et ses médias associés.
- Multi-langue : la structure des blocs est partagée entre toutes les langues, mais le contenu (textes, images) est édité indépendamment par langue.
Blocs disponibles
Contenu texte
| Bloc | Description |
|---|---|
paragraph | Paragraphe avec éditeur de texte riche (Redactor) |
heading | Titre avec sélecteur de niveau (H1 à H4) |
quote | Citation avec attribution |
code | Bloc de code avec coloration syntaxique (HTML, CSS, JavaScript, PHP, JSON, Bash) |
list | Liste ordonnée ou non ordonnée |
Médias
| Bloc | Description |
|---|---|
image | Image unique avec texte alternatif et légende |
gallery | Galerie d’images en grille |
cover | Image de couverture plein écran avec titre et sous-titre en overlay |
video | Embed YouTube ou Vimeo via URL, avec preview live |
map | Carte Google Maps ou OpenStreetMap par adresse |
Mise en page
| Bloc | Description |
|---|---|
separator | Ligne de séparation horizontale (marge et style configurables) |
Blocs avancés
| Bloc | Description |
|---|---|
author | Affiche les informations d’un auteur depuis un modèle Eloquent |
logo-cloud | Grille de logos avec liens optionnels |
form | Formulaire dynamique avec validation, envoi d’email et historique des soumissions |
Configuration de la ressource
L’ajout du Page Builder à une ressource se fait via le champ PageBuilder :
use Lochness\Fields\PageBuilder;
public function fields(): array
{
return [
PageBuilder::make('Contenu', 'block_builder')
->translated()
->blocks([
'paragraph',
'heading',
'image',
'gallery',
'video',
'quote',
'form',
]),
];
}La colonne en base doit être de type longText ou json :
$table->longText('block_builder')->nullable();Méthodes disponibles
| Méthode | Description |
|---|---|
->blocks([...]) | Liste des types de blocs autorisés |
->translated() | Active le support multi-langue |
->configure('type', [...]) | Configure un bloc spécifique (toolbar Redactor, modèle Eloquent, etc.) |
->preformatted([...]) | Enregistre des blocs personnalisés (voir ci-dessous) |
Exemples de configuration
PageBuilder::make('Contenu', 'block_builder')
->blocks(['paragraph', 'author'])
->configure('paragraph', [
'toolbar' => ['bold', 'italic', 'link'],
])
->configure('author', [
'model' => \App\Models\Author::class,
'display' => 'full_name',
'order_by' => 'first_name',
])Bloc Formulaire
Le bloc form permet de créer des formulaires dynamiques sans écrire de code. Il prend en charge :
- Les types de champs :
text,email,textarea,radio,checkbox - La validation côté serveur
- Le layout en colonnes (demi ou pleine largeur)
- L’envoi d’un email au destinataire configuré, avec copie optionnelle au visiteur
- L’historique des soumissions consultable dans
/cockpit/forms - La protection anti-spam : honeypot + rate limiting (5 requêtes/min/IP)
- Le reCAPTCHA v3 (optionnel)
Configuration reCAPTCHA
Dans le fichier .env :
RECAPTCHA_SITE_KEY=your_site_key
RECAPTCHA_SECRET_KEY=your_secret_keyDans config/services.php :
'recaptcha' => [
'site_key' => env('RECAPTCHA_SITE_KEY'),
'secret_key' => env('RECAPTCHA_SECRET_KEY'),
],Configuration Google Maps
Pour utiliser l’API Embed officielle dans le bloc map, ajoutez dans .env :
GOOGLE_MAPS_KEY=your_keyEt dans config/services.php :
'google_maps' => ['key' => env('GOOGLE_MAPS_KEY')],Sans clé, un fallback OpenStreetMap est utilisé automatiquement.
Rendu frontend
L’affichage des blocs sur le site se fait avec la directive Blade @blocks :
@blocks($model, 'block_builder', app()->getLocale(), 'actualites.modules')| Paramètre | Description |
|---|---|
$model | Instance du modèle Eloquent |
'block_builder' | Nom de l’attribut Page Builder |
locale | Code langue (optionnel, défaut : locale courante) |
viewPath | Préfixe de vue pour personnaliser le rendu (optionnel) |
Résolution des vues
Le renderer cherche les vues dans cet ordre :
- Vue personnalisée du projet :
{viewPath}.{type}(ex :actualites.modules.heading) - Vue d’un bloc preformatted : la valeur retournée par
frontView() - Vue par défaut du package :
lochness::front.page-builder.blocks.{type}
Variables disponibles dans les vues
| Variable | Description |
|---|---|
$block | Structure complète du bloc |
$content | Contenu traduit du bloc |
$data | Données statiques (structure.data) |
$blockSettings | Settings du bloc (_settings) |
$media | Média associé (Spatie Media Library) ou null |
$model | Instance du modèle parent |
$locale | Code langue actuel |
$blockId | Identifiant unique du bloc |
$type | Type du bloc |
$attribute | Nom de l’attribut Page Builder |
Utilisez
$blockSettingset non$settings. La variable$settingspeut être écrasée par unView::composer('*').
Exemple de vue personnalisée
{{-- resources/views/actualites/modules/heading.blade.php --}}
@php $level = $blockSettings['level'] ?? 2; @endphp
<h{{ $level }} class="font-bold text-2xl">
{{ $content['text'] ?? '' }}
</h{{ $level }}>Blocs personnalisés (preformatted)
Pour créer un type de bloc spécifique au projet, étendez AbstractPreformattedBlock :
namespace App\Modules\Preformatted;
use Lochness\Fields\PageBuilder\AbstractPreformattedBlock;
class TestimonialBlock extends AbstractPreformattedBlock
{
public static function type(): string
{
return 'testimonial';
}
public static function name(): string
{
return 'Témoignage';
}
public function fields(): array
{
return [
['name' => 'title', 'type' => 'heading', 'label' => 'Titre', 'levels' => [2, 3]],
['name' => 'description', 'type' => 'richtext', 'label' => 'Description'],
];
}
public function repeatable(): array
{
return [
['name' => 'name', 'type' => 'text', 'label' => 'Nom', 'required' => true],
['name' => 'quote', 'type' => 'richtext', 'label' => 'Témoignage', 'required' => true],
];
}
public function frontView(): string
{
return 'modules.preformatted.testimonial.front';
}
}Puis enregistrez la classe dans la ressource :
PageBuilder::make('Contenu', 'block_builder')
->blocks(['paragraph', 'heading'])
->preformatted([
\App\Modules\Preformatted\TestimonialBlock::class,
])Types de champs supportés
| Type | Description |
|---|---|
text | Champ texte |
textarea | Zone de texte multi-lignes |
heading | Texte avec sélecteur de niveau H1-H4 |
richtext | Éditeur Redactor complet |
Méthodes de l’interface
| Méthode | Rôle |
|---|---|
type() | Identifiant unique du bloc |
name() | Nom affiché dans l’éditeur |
icon() | Icône SVG (taille size-5) |
fields() | Champs principaux (traduits) |
settings() | Paramètres du bloc (non traduits) |
repeatable() | Items répétables |
hasImage() | Activation et configuration de l’image |
frontView() | Vue Blade pour le rendu frontend |
editorView() | Vue éditeur personnalisée (optionnel) |
Structure des données
Le Page Builder stocke ses données en JSON dans un seul champ. La structure (ordre, types, settings) est partagée entre toutes les langues, le contenu est indexé par locale :
{
"structure": [
{ "id": "blk_abc12345", "type": "heading", "position": 0, "data": { "_settings": { "level": "2" } } }
],
"content": {
"fr": { "blk_abc12345": { "text": "Mon titre" } },
"en": { "blk_abc12345": { "text": "My title" } }
}
}Gestion des médias
Les images sont stockées via Spatie Media Library, dans des collections nommées :
pagebuilder_{attribute}_{blockId}_{locale}Pour les blocs avec images par item (par exemple logo-cloud) :
pagebuilder_{attribute}_{blockId}_{itemId}_{locale}Quand un bloc est supprimé, toutes ses collections media (fichiers + entrées en base) sont supprimées automatiquement.