Laravel 11

Sillo – les layouts

Pour ce projet, il m’a fallu prendre des décisions technologiques importantes. J’ai hésité à adopter Livewire, mais j’ai finalement cédé. Bien que j’apprécie coder en JavaScript, cela n’est plus vraiment nécessaire sauf pour des cas spécifiques. Par conséquent, j’ai opté pour Livewire, Volt et MaryUI, tout comme je l’avais fait pour ma série d’articles sur les albums photos. Grâce à ces technologies, on gagne beaucoup de temps dans le développement web, même si cela nécessite un investissement initial en termes d’apprentissage.

Livewire, Volt et MaryUI offrent une combinaison puissante pour développer rapidement des interfaces utilisateur riches et réactives. Ils facilitent la création de composants réutilisables et la gestion de l’application sans avoir à gérer manuellement les mises à jour DOM.

Parmi les principaux avantages de ces technologies, on peut citer :

  • Livewire : simplifie la communication entre le frontend et le backend, ce qui permet de créer rapidement des interfaces utilisateur interactives sans devoir écrire du JavaScript.
  • Volt : un langage de template rapide et flexible qui s’intègre parfaitement avec Livewire et Laravel.
  • MaryUI : une bibliothèque de composants UI complets et prêts à l’emploi, qui facilite la conception d’interfaces utilisateur attrayantes et cohérentes.

Bien qu’il puisse être nécessaire de consacrer un peu de temps pour apprendre à utiliser ces technologies, le retour sur investissement en termes de productivité est important. Je suis convaincu que cette panoplie technologique est un atout précieux pour le développement de mon projet et pourra intéresser ceux qui souhaitent participer à sa création.

LiveWire Volt

Livewire et Volt sont deux technologies complémentaires qui offrent une expérience de développement web innovante et efficace. Ensemble, ces outils aident à créer des applications web interactives tout en réduisant la complexité du développement frontend et en bénéficiant de l’écosystème Laravel.

Livewire est un framework JavaScript complet pour Laravel qui simplifie la construction de frontends dynamiques et réactifs sans avoir à écrire beaucoup de code JavaScript, et souvent pas du tout. Il permet aux développeurs de séparer les préoccupations liées au frontend et au backend en permettant de gérer la logique d’une application directement des contrôleurs PHP, tout en rendant les vues dynamiques et réactives.

Volt est un langage de template rapide et flexible pour PHP et Laravel. Il s’intègre parfaitement avec Livewire et offre une syntaxe concise et lisible pour la génération de vues. Volt rend le développement de templates plus agréable en fournissant une compatibilité étendue avec Laravel et en améliorant la productivité grâce à ses structures de contrôle et sa gestion des données.

Les principaux avantages de l’utilisation de Livewire et Volt sont :

  • Un développement frontend plus rapide et moins complexe, en réduisant la nécessité de gérer des librairies JavaScript supplémentaires.
  • Une intégration avec Laravel et son écosystème.
  • Un développement efficace en séparant les préoccupations du frontend et du backend.
  • Des performances élevées grâce à l’utilisation de websockets pour les communications en temps réel entre le serveur et le navigateur.
  • Un langage de template propre, facile à utiliser et à lire, grâce à Volt.

En fin de compte, l’utilisation de Livewire et Volt améliore considérablement une expérience de développement Laravel en réduisant la complexité, en offrant une productivité accrue et en permettant de créer des applications web modernes et performantes.

MaryUI

MaryUI est une bibliothèque de composants web légers et accessibles conçue pour aider les développeurs à créer rapidement des interfaces utilisateur attrayantes et cohérentes. Basée sur le framework Tailwind CSS et sur DaisyUI, MaryUI est entièrement personnalisable et peut s’adapter parfaitement aux projets web, qu’ils soient des applications web, des sites web ou des dashboards.

Les principales caractéristiques de MaryUI incluent :

  • Un ensemble de composants complets : MaryUI fournit une large gamme de composants prêts à l’emploi tels que des boutons, des formulaires, des cartes, des modales et plus encore, qui peuvent être facilement intégrés aux projets.
  • Basée sur Tailwind CSS : Comme MaryUI est construite sur Tailwind CSS, vous bénéficiez de la flexibilité, de la puissance et de la communauté établie de Tailwind CSS pour la création de designs uniques et responsifs.
  • Basée su DaisyUI : c’est une bibliothèque de composants légers et modernes conçue pour s’intégrer parfaitement avec Tailwind CSS. Elle offre une large gamme de composants pré-construits et personnalisables, tels que des boutons, des formulaires, des cartes et des modales, pour accélérer votre workflow de développement.
  • Accessibilité : MaryUI est conçue avec l’accessibilité en tête, garantissant une expérience utilisateur optimale pour toutes les personnes, quelle que soit leur capacité.
  • Personnalisation : Les composants MaryUI peuvent être simplement personnalisés pour correspondre au style et aux exigences de votre projet, grâce à la puissance de Tailwind CSS.
  • Intégration avec Livewire et Volt : MaryUI est également conçue pour s’intégrer parfaitement avec Livewire et Volt, ce qui rend la création d’interfaces utilisateur interactives encore plus facile et rapide.

En utilisant MaryUI dans vos projets web, vous pouvez accélérer le processus de développement en bénéficiant d’un ensemble cohérent de composants personnalisables, tout en créant des interfaces utilisateur attrayantes et accessibles pour vos utilisateurs.

Les layouts

Les composants Volt ont besoin d’un layout. Par défaut un composant Volt va cher son layout ici : views/components/lauouts/app.blade.php. Mais il est facile de dire à un composant d’aller cher son layout ailleurs :

use Livewire\Attributes\Layout;

new
#[Layout('components.layouts.auth')]
class extends Component {

Dans l’application, il y a 3 layouts :

  • admin.blade.php : la mise en page réservée à l’administration (backend)
  • app.blade.php : la mise en page pour l’accueil, les articles, les pages…
  • auth.blade.php : la mise en page pour tout ce qui concerne l’authentification : connexion, enregistrement, gestion du mots de passe…

Layout app

Le layout app est celui qui s’occupe du visuel principal du site : page d’accueil, articles, etc… Il est divisé en 4 zones :

  • un header avec une image banniere
  • une barre de navigation (qui se transforme en barre latérale sur petit écran) avec un menu, un contrôle d etexte pour la recherche sur le site, un bouton de changement de thème (light ou dark)
  • une zone de contenu
  • un footer avec un menu pour les pages fixes

Voici le code simplifié :

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    ...    
</head>
<body class="min-h-screen font-sans antialiased bg-base-200/50 dark:bg-base-200">
    {{-- IMAGE --}}
    <div class="flex flex-wrap">
        <a href="{{ url('/') }}" class="block w-full">
            <img src="{{ asset('storage/banniere.png') }}" class="w-full" alt="Laravel">
        </a>
    </div>

    {{-- NAVBAR --}}
    <livewire:navigation.navbar :$menus />

    {{-- MAIN --}}
    <x-main full-width>

        {{-- SIDEBAR --}}
        <x-slot:sidebar drawer="main-drawer" collapsible class="bg-base-100 lg:bg-inherit lg:hidden">
            <livewire:navigation.sidebar :$menus />            
        </x-slot:sidebar>

        {{-- SLOT --}}
        <x-slot:content>
            {{ $slot }}
        </x-slot:content>
        
    </x-main>

    {{-- FOOTER --}}
    <hr><br>
        <livewire:navigation.footer /> 
    <br>    

</body>
</html>

Voici un visuel :

Sur un écran moins large, on n’a que deux cadres d’articles et un bouton pour l’ouverture du menu latéral :

On conserve toutefois le bouton pour le thème et le contrôle pour la recherche. Notez que l’aspect « responsive » du contenu n’est évidemment pas géré par le layout mais par le contenu lui-même.

Le header est constitué d’une simple image qui a aussi un lien vers la page d’accueil. En effet, on n’a pas besoin d’une grande interactivité à ce niveau, c’est plutôt un élément esthétique et informatif.

Pour la navigation, on utilise un composant :

On voit qu’on a aussi un composant pour la barre latérale (sidebar) et le footer.

Pour le contenu, c’est juste un slot dans le layout.

Cette organisation par zones et composants est vraiment pratique.

Layout auth

Ce layout est dévolu à tout ce qui concerne l’authentification, il est donc bien épuré par rapport au précédent. Voici le code simplifié :

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    ...
</head>
<body class="min-h-screen font-sans antialiased bg-base-200/50 dark:bg-base-200">

    <x-main full-width>
        <x-slot:content>
            {{ $slot }}
        </x-slot:content>
    </x-main>

    {{-- FOOTER --}}
    <hr><br>
        <livewire:navigation.footer /> 
    <br> 

    {{--  TOAST area --}}
    <x-toast />
    
</body>
</html>

On a donc le même que le précédent, mais sans le header et sans la navigation. On conserve uniquement le contenu et le footer.

Le layout admin

Ce layout, comme son nom l’indique, est consacré à la partie administration du site. Avec ce layout on n’a que deux zones : la barre de navigation latérale et le contenu :

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    ...

    {{-- <script src="https://cdn.tiny.cloud/1/wh0id6mlubx6aquz5st36jf7mxqdippaaayzeocsibux2vft/tinymce/7/tinymce.min.js" referrerpolicy="origin"></script> --}}

    <script src="{{ asset('storage/scripts/tinymce.min.js') }}" referrerpolicy="origin"></script>

</head>
<body class="min-h-screen font-sans antialiased bg-base-200/50 dark:bg-base-200">

    {{-- MAIN --}}
    <x-main full-width>

        {{-- SIDEBAR --}}
        <x-slot:sidebar drawer="main-drawer" collapsible class="bg-base-100">
            <livewire:admin.sidebar />            
        </x-slot:sidebar>

        <x-slot:content>            
            <!-- Drawer toggle for "main-drawer" -->
            <label for="main-drawer" class="mr-3 lg:hidden">
                <x-icon name="o-bars-3" class="cursor-pointer" />
            </label>
            {{ $slot }}
        </x-slot:content>
        
    </x-main>

    {{--  TOAST area --}}
    <x-toast />

</body>
</html>

On va aussi charger des ressources complémentaires pour l’éditeur TinyMCE qui va bien nous servir pour créer articles et pages.

L’aspect est épuré et adapté au côté utilistaire d’une adminustration de site :

Analyse du composant navbar

L’analyse de ce composant Volt est un bon exemple. Il utilise MaryUI et implique la compréhension de plusieurs éléments clés : l’utilisation de Livewire pour la réactivité côté client, l’interaction avec l’authentification Laravel, et la structuration de l’interface utilisateur avec des composants Blade personnalisés de MaryUI.

Voici le code complet de ce composant :

<?php

use Livewire\Volt\Component;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use App\Models\Menu;
use Illuminate\Support\Collection;

new class extends Component 
{
    public Collection$menus;

    // Initialise le composant avec les menus donnés.
    public function mount($menus)
    {
        $this->menus = $menus;
    }

    // Déconnecte l'utilisateur actuellement authentifié.
    public function logout(): void
    {
        Auth::guard('web')->logout();

        Session::invalidate();
        Session::regenerateToken();

        $this->redirect('/');
    }

}; ?>

<x-nav sticky full-width>
    <x-slot:brand>
        <label for="main-drawer" class="lg:hidden mr-3">
            <x-icon name="o-bars-3" class="cursor-pointer" />
        </label>
    </x-slot:brand>

    <x-slot:actions> 
        <span class="hidden lg:block">
            @if($user = auth()->user())
                <x-dropdown>
                    <x-slot:trigger>
                        <x-button label="{{ $user->name }} " class="btn-ghost" />
                    </x-slot:trigger>
                    <x-menu-item title="{{ __('Profile') }}" link="{{ route('profile') }}" />
                    <x-menu-item title="{{ __('Logout') }}" wire:click="logout" />
                    @if($user->isAdminOrRedac())
                        <x-menu-item title="{{ __('Administration') }}" link="{{ route('admin') }}" />
                    @endif
                </x-dropdown>   
            @else
                <x-button label="{{ __('Login') }}" link="/login" class="btn-ghost" />
            @endif

            @foreach ($menus as $menu)                
                @if($menu->submenus->isNotEmpty())
                    <x-dropdown>
                        <x-slot:trigger>
                            <x-button label="{{$menu->label}}" class="btn-ghost" />
                        </x-slot:trigger>
                        @foreach ($menu->submenus as $submenu)
                            <x-menu-item title="{{ $submenu->label }}"  link="{{ $submenu->link }}" style="min-width: max-content;" />
                        @endforeach
                    </x-dropdown>
                @else
                    <x-button label="{{ $menu->label }}" link="{{ $menu->link }}" class="btn-ghost" />
                @endif
            @endforeach
        </span>
        <x-theme-toggle />
        <livewire:search />  
    </x-slot:actions>
</x-nav>

Passons en revue ce code…

Utilisation des namespaces et des classes Laravel :

  • use Livewire\Volt\Component; : Utilise le composant Livewire Volt pour créer des composants interactifs.
  • use Illuminate\Support\Facades\Auth; : Gère l’authentification des utilisateurs.
  • use Illuminate\Support\Facades\Session; : Gère les sessions utilisateur.
  • use App\Models\Menu; : Utilise le modèle Menu pour récupérer les données de menu.
  • use Illuminate\Support\Collection; : Utilise la classe Collection de Laravel pour manipuler des collections de données.

Propriétés et méthodes du composant :

  • public Collection $menus; : Propriété pour stocker les menus, typée en tant que collection.
  • public function mount($menus) : Méthode d’initialisation du composant qui prend les menus en paramètre et les assigne à la propriété $menus.
  • public function logout(): void : Méthode pour déconnecter l’utilisateur. Cette méthode :
    • Déconnecte l’utilisateur via Auth::guard('web')->logout().
    • Invalide la session actuelle avec Session::invalidate().
    • Regénère le token CSRF avec Session::regenerateToken().
    • Redirige l’utilisateur vers la page d’accueil avec $this->redirect('/').

Analyse des composants Blade

  1. Composant de navigation <x-nav> :
    • Attributs sticky et full-width pour définir le comportement et le style de la navigation.
  2. Slot brand :
    • Contient un label pour ouvrir le menu sur les petits écrans (lg:hidden) avec une icône de barre.
  3. Slot actions :
    • Vérifie si l’utilisateur est authentifié :
      • Si oui, affiche un dropdown avec des options de profil, déconnexion et administration si l’utilisateur a des privilèges admin ou rédacteur.
      • Si non, affiche un bouton de connexion.
    • Parcourt les menus et affiche un bouton ou un dropdown selon la présence de sous-menus.
    • Affiche des composants supplémentaires pour basculer le thème (<x-theme-toggle />) et une barre de recherche (<livewire:search />).

Ce composant combine des fonctionnalités de Livewire et de Laravel avec des composants Blade personnalisés pour créer une interface utilisateur dynamique et réactive. L’utilisation de slots et de conditions permet de personnaliser le contenu affiché en fonction de l’état d’authentification de l’utilisateur et des données de menu. Les méthodes de déconnexion et de redirection gèrent la sécurité et l’expérience utilisateur de manière fluide.

Le composant search

Voici le composant search qui est intégré dans la navigation :

<?php

use Livewire\Volt\Component;
use Livewire\Attributes\Rule;

new class extends Component {
  
    // Propriété pour le champ de recherche avec validation
    #[Rule('required|string|max:100')]
    public string $search = '';

    /**
     * Sauvegarde la recherche et redirige vers la page de résultats de recherche.
     * 
     * @return \Illuminate\Http\RedirectResponse
     */
    public function save()
    {
        $data = $this->validate();

        return redirect('/search/' . $data['search']);
    }
};
?>

<div>
    <!-- Formulaire de recherche -->
    <form wire:submit.prevent="save">
        <x-input 
            placeholder="{{ __('Search') }}..."
            wire:model="search"
            clearable
            icon="o-magnifying-glass"
        />
    </form>
</div>

Ce code crée un composant Volt qui implémente un champ de recherche avec validation et une fonctionnalité de redirection vers une page de résultats de recherche. Voici une explication détaillée :

  1. Propriété $search :
    • Cette propriété est définie avec une validation. Elle utilise l’attribut de validation #[Rule('required|string|max:100')].
    • Cela signifie que le champ de recherche est requis, doit être une chaîne de caractères et ne peut pas dépasser 100 caractères de longueur.
  2. Méthode save :
    • Cette méthode est appelée lorsque le formulaire de recherche est soumis.
    • Elle valide les données entrées dans le champ de recherche en utilisant la méthode validate() de Livewire, qui utilise les règles de validation définies dans la propriété $search.
    • Si la validation réussit, elle redirige l’utilisateur vers une page de résultats de recherche en utilisant la fonction redirect() de Laravel, en passant le terme de recherche saisi dans l’URL, on fait donc appel au composant index décrit ci-dessus.
  3. Formulaire de recherche :
    • Un formulaire Livewire est utilisé pour gérer la soumission du champ de recherche.
    • Le formulaire utilise la directive wire:submit.prevent="save" pour appeler la méthode save() lorsque le formulaire est soumis, en empêchant le comportement par défaut de rechargement de la page.
    • À l’intérieur du formulaire, il y a un composant MaryUI <x-input> qui représente le champ de recherche.
    • Le champ de recherche est lié à la propriété $search du composant Livewire via l’attribut wire:model="search", ce qui signifie que toute modification du champ de recherche sera automatiquement synchronisée avec la propriété $search.
    • Le champ de recherche est doté d’un bouton pour effacer le texte (clearable) et d’une icône de loupe (icon="o-magnifying-glass").

Tous les composants créés pour ce projets sont constitués sur le même schéma. Le fait de disposer dans un même fichier de la partie PHP et HTML est bien pratique.

Conclusion

Ces layouts constituent la structuration essentielle de l’application et son visuel. On pourrait envisager de rendre cette partie modulable pour facilement changer l’aspect du site. Avec l’approche par composants ce n’est pas très difficile.

Print Friendly, PDF & Email

Un commentaire

  • GrCOTE7

    Encore Bravo !

    Ces choix est excellent, pour avoir un tel rendu, « en si peu » de code ‘perso’…

    Et je rappelle à quiconque qui ‘arrive ici’, que juste 7-8 commandes en console, et vous l’avez en local !!!

    https://github.com/bestmomo/sillo/blob/master/installation.md

    Et à noter, que si vous utilisez ce qui est préconisé dans le .env, pour juste du dev, et donc sqlite, pas besoin de laragon ou de quelconque autre serveur de SGBD ! Un simple…:

    « `
    php artisan serv
    « `
    Et tout fonctionne nickel :-), avec, cerise sur le gâteau…? : Le hot refresh !!!

    Vous changez un caractère dans votre éditeur, si l’option enregistrement automatique est activé, que vous avez mis l’éditeur d’un côté de votre écran, le navigateur de l’autre, vous voyez alors immédiatement le rendu !!!

    Bref, oui, vraiment, une bonne base, et encore bravo, BestMomo ! 🙂

    @++, avec plaisir 🙂
    PS: Rien à dire sur tes choix technomogiques 🙂 ! À mon avis, même un gars qui débute, s’il s’investit sur ces 4-5 technos, seule son imagination (ou son employeur…?) le limitera !!!

Laisser un commentaire