Nous allons maintenant détailler notre application en examinant la façon de présenter les articles et les pages, qui sont les éléments clés de ce genre d'application. Si les pages sont simples à gérer, car elles sont isolées, les articles nécessitent une attention particulière en raison de leurs relations avec les catégories et les séries, ainsi que la gestion des commentaires.
Pour la présentation des articles, nous devons prendre en compte les éléments suivants :
- Affichage de la catégorie : Lors de la consultation d'un article, l'affichage de la catégorie associée est essentiel. Cela permet aux utilisateurs de connaître rapidement le contexte de l'article et de naviguer dans les articles similaires.
- Gestion des séries : Pour les articles faisant partie d'une série, il est important d'afficher cette information et de permettre une navigation spécifique au sein de cette série. Ceci inclura l'affichage des liens vers les articles précédents et suivants de la série.
- Gestion des commentaires : La gestion des commentaires nécessite une attention particulière. Nous devons intégrer une zone de saisie de commentaires pour les utilisateurs connectés, ainsi qu'une liste de tous les commentaires précédents.
Les pages
On va commencer par le plus simple avec les pages. On a cette route pour l'affichage :Volt::route('/pages/{page:slug}', 'pages.show')->name('pages.show');
Et ce composant Volt :
Avec ce simple code :
<?php
use Livewire\Volt\Component;
use App\Models\Page;
// Création d'une nouvelle classe anonyme étendant Component
new class extends Component {
// Propriété publique pour stocker la page
public Page $page;
// Méthode de montage pour initialiser la page
public function mount(Page $page): void
{
$this->page = $page;
}
}; ?>
<!-- Vue du composant -->
<div>
<!-- Entête de la page -->
<x-header title="{!! $page->title !!}" />
<!-- Contenu de la page -->
<div class="relative items-center w-full px-5 py-5 mx-auto prose md:px-12 max-w-7xl">
{!! $page->body !!}
</div>
</div>
Je ne détaille pas le code, on a une simple propriété $page qui contient toutes les informations de la page et on l'envoie dans la vue.
On affiche le titre et le contenu :
Les articles
Pour les articles, on a un peu plus de données à gérer. Voici la route :
Volt::route('/posts/{slug}', 'posts.show')->name('posts.show');
On ne prend pas la peine de faire une liaison pour récupérer directement le modèle parce qu'on va devoir charger pas mal d'autres informations.
Le composant Volt est ici :La méthode mount
On a une méthode mount appelée au départ :// Initialise le composant avec le post spécifié.
public function mount($slug): void
{
// Instanciation d'un nouveau repository de post
$postRepository = new PostRepository;
// Récupération du post par le slug
$this->post = $postRepository->getPostBySlug($slug);
// Remplissage des propriétés next et previous du post
$this->fill($this->post->only('next', 'previous'));
// Comptage des commentaires valides du post
$this->commentsCount = $this->post->valid_comments_count;
// Initialisation d'une collection de commentaires
$this->comments = new Collection();
}
Elle récupère les détails de l'article correspondant au slug fourni, remplit les propriétés next
et previous
qui vont être utiles dans le cas d'une série, compte le nombre de commentaires valides et initialise une collection vide pour stocker les commentaires.
public function getPostBySlug(string $slug): Post
{
$post = Post::with('user:id,name', 'category', 'serie')
->withCount('validComments')
->whereSlug($slug)
->firstOrFail();
if ($post->serie_id) {
$post->previous = $post->parent_id ? Post::findOrFail($post->parent_id) : null;
$post->next = Post::whereParentId($post->id)->first() ?: null;
}
return $post;
}
On voit qu'on charge les informations sur l'auteur de l'article, la catégorie et la série éventuelle.
La partie supérieure
La partie supérieure est gérée par ce code :<!-- Actions disponibles pour les utilisateurs authentifiés -->
<div class="flex justify-end gap-4">
@auth
<!-- Bouton pour modifier le post -->
@if(Auth::user()->isAdmin() || Auth::user()->id == $post->user_id)
<x-button icon="c-pencil-square" link="{{ route('posts.edit', $post) }}" tooltip-left="{{ __('Edit') }}" spinner class="btn-ghost btn-sm" />
<x-button icon="o-finger-print" wire:click="clonePost({{ $post->id }})" tooltip-left="{{ __('Clone') }}" spinner class="btn-ghost btn-sm" />
@endif
@endauth
<!-- Bouton pour afficher la catégorie du post -->
<x-button class="btn-sm"><a href="{{ url('/category/' . $post->category->slug) }}">{{ $post->category->title }}</a></x-button>
<!-- Bouton pour afficher la série du post (s'il existe) -->
@if($post->serie)
<x-button class="btn-sm"><a href="{{ url('/serie/' . $post->serie->slug) }}">{{ $post->serie->title }}</a></x-button>
@endif
</div>
Au minimum, on affiche un bouton pour la catégorie à laquelle appartient l'article. Un clic sur ce bouton affiche les articles de cette catégorie.
On a ensuite des affichages optionnels :- un bouton pour modifier l'article si on est en présence de l'administrateur ou de l'auteur
- un bouton pour cloner l'article si on est en présence de l'administrateur ou de l'auteur
- un bouton pour la série éventuelle à laquelle appartient l'article. Un clic sur ce bouton affiche les articles de cette série.
Juste au-dessous, on trouve le titre de l'article et sa date de publication :
<!-- Titre et date du post -->
<x-header title="{!! $post->title !!}" subtitle="{{ $post->created_at->isoFormat('LL') }} " />
Le contenu de l'article
On a ensuite le contenu de l'article géré avec ce code :<!-- Contenu du post -->
<div class="relative items-center w-full px-5 py-5 mx-auto prose md:px-12 max-w-7xl">
<div class="flex flex-col items-center mb-4">
<img src="{{ asset('storage/photos/' . $post->image) }}" />
</div>
<br>
{!! $post->body !!}
</div>
<br><hr>
Avec deux éléments :
- l'image d'en-tête
- le corps de l'article
L'auteur et le nombre de commentaires
Au-dessous, on informe sur le nom de l'auteur de l'article et le nombre de commentaires :<!-- Informations sur l'auteur et le nombre de commentaires -->
<div class="flex justify-between">
<p>@lang('By ') {{ $post->user->name }}</p>
<em>
@if($commentsCount != 0)
@lang('Number of comments: ') {{ $commentsCount }}
@else
@lang('No comments')
@endif
</em>
</div>
Et s'il n'y a pas de commentaires :
Les séries
Si l'article appartient à une série, il faut afficher la navigation :<!-- Navigation entre les posts de la série -->
@if($post->serie)
<br>
<div class="{{ $previous ? 'flex justify-between' : 'flex justify-end' }}">
@if($previous)
<x-button label="{{ __('Previous') }}" icon="s-arrow-left" link="{{ url('/posts/' . $previous->slug) }}" class="btn-sm" />
@endif
@if($next)
<x-button label="{{ __('Next') }}" icon-right="s-arrow-right" link="{{ url('/posts/' . $next->slug) }}" class="btn-sm" />
@endif
</div>
@endif
Les commentaires
En dernier, on a la zone des commentaires. Voici le code correspondant :<!-- Section des commentaires -->
<div class="relative items-center w-full px-5 py-5 mx-auto md:px-12 max-w-7xl">
@if($listComments)
<!-- Afficher les commentaires -->
<x-card title="{{ __('Comments') }}" shadow separator >
@foreach ($comments as $comment)
@if(!$comment->parent_id)
<livewire:posts.comment :$comment :$comments :depth="0" :key="$comment->id" />
@endif
@endforeach
<!-- Formulaire pour ajouter un nouveau commentaire -->
@auth
<livewire:posts.commentBase :postId="$post->id" />
@endauth
</x-card>
@else
<!-- Afficher le bouton pour afficher les commentaires -->
@if($commentsCount > 0)
<div class="flex justify-center">
<x-button label="{{ $commentsCount > 1 ? __('View comments') : __('View comment') }}" wire:click="showComments" class="btn-outline" />
</div>
<!-- Afficher le formulaire pour ajouter un commentaire si aucun commentaire n'est disponible -->
@else
@auth
<livewire:posts.commentBase :postId="$post->id" />
@endauth
@endif
@endif
</div>
Au chargement de l'article, on se contente d'afficher un bouton pour charger les commentaires (s'il y en a) :
S'il n'y a pas de commentaire, on affiche directement le formulaire pour en créer un (si le visiteur est authentifié) :
Si on clique sur le bouton pour afficher les commentaires, alors ils s'affichent :
J'écrirai un article spécifique sur le sujet des commentaires qui constitue la partie la plus délicate au niveau codage.
Conclusion
Cet affichage des articles est évidemment la partie la plus importante de l'application. Je pense avoir rassemblé tous les élément sessentiels.Par bestmomo
Nombre de commentaires : 5