Guide Blade
Le package fournit sept directives Blade pour les applications rendues côté serveur. L'une d'elles, @seo, suffit dans la plupart des cas.
La directive tout-en-un
<!DOCTYPE html>
<html>
<head>
@seo($post)
</head>@seo résout le modèle selon la chaîne de priorité et produit l'ensemble du bloc head : <title>, meta description, lien canonical, robots, balises Open Graph, Twitter Cards et JSON-LD associé. La balise robots apparaît uniquement si sa valeur diffère de la valeur par défaut du site. Un index,follow redondant est omis, puisque l'absence de balise correspond déjà à ce comportement. Activez seo.robots.emit_default pour toujours l'afficher. Consultez le contrat de rendu complet.
Signatures :
@seo($post) {{-- model page --}}
@seo($seoData) {{-- a hand-built SEOData (model-less page) --}}
@seo($post, 'blog.show') {{-- model + route defaults --}}
@seo($post, null, 'fr') {{-- model + locale --}}
@seo(null) {{-- current page, no model --}}@seo accepte un Model, un SEOData construit manuellement ou null. Les arguments de route et de langue s'appliquent uniquement au chemin Model/null. Un SEOData construit manuellement porte ses propres valeurs.
Pages de route sans modèle
Pour les pages statiques, archives et autres pages définies par une route :
@seoForRoute('pages.about')
@seoForRoute('contact', 'de') {{-- with locale --}}Les valeurs de route proviennent des lignes de seo_defaults associées au nom de la route.
Pages sans modèle : construire un SEOData
Une liste, des résultats de recherche ou une page composée dans un contrôleur n'ont pas toujours un modèle unique. Construisez un SEOData et passez-le directement à @seo ou à la façade SEO, sans appeler app(TagRenderer::class)->render(...) :
use Rankbeam\Seo\Data\SEOData;
return view('search.results', [
'seo' => new SEOData(
title: "Results for \"{$query}\"",
description: "Browse {$count} matches for {$query}.",
ogImage: '/images/search-share.jpg', // relative is fine — see below
),
]);<head>
@seo($seo)
</head>Un SEOData construit manuellement est traité comme une intention explicite. Les valeurs fournies sont conservées ; seuls les éléments manquants suivants sont complétés au rendu :
canonicaletog:urlsont dérivés de l'URL courante s'ils sont absents. Uncanonicalexplicite est conservé tel quel, paramètres de requête compris.title_suffixest ajouté seulement si le titre ne le contient pas déjà. Il est entièrement ignoré si le titre contient déjà un terme de marque configuré ; voirtitle_suffix_skip_when_contains.- Les chemins relatifs de
og:imageettwitter:imagedeviennent absolus avecurl(), qui respecte le protocole courant et ne force pas HTTPS. og:site_nameetlocalesont complétés à partir de la configuration et de la langue de l'application.
La chaîne de priorité en base de données – valeurs globales, par type de modèle, par route et seo_meta – n'est pas fusionnée avec un SEOData construit manuellement. Le rendu utilise ce que vous fournissez, avec les compléments ci-dessus.
La même valeur fonctionne avec la façade :
SEO::render($seoData); // HTML string
SEO::toArray($seoData); // Vue/React structure
SEO::forInertia($seoData); // Inertia Head structureUn layout commun à plusieurs types de pages
Un seul layout peut servir les pages de modèle, les pages de route et les autres pages :
<head>
@if(isset($seoModel))
@seo($seoModel)
@elseif(isset($seoRoute))
@seoForRoute($seoRoute)
@else
@seo(null)
@endif
</head>Les contrôleurs passent alors 'seoModel' => $post ou 'seoRoute' => 'blog.index' sans manipuler le balisage.
Directives spécialisées
Pour contrôler les balises individuellement, par exemple en combinant leur rendu avec celui d'un autre package :
| Directive | Rendu |
|---|---|
@seoTitle($post) | Uniquement <title> |
@seoMeta($post) | Uniquement la meta description |
@seoCanonical($post) | Uniquement le lien canonical, avec repli sur l'URL courante |
@seoRobots($post) | Uniquement la balise meta robots, toujours affichée. Cet appel explicite n'applique pas la suppression des valeurs par défaut utilisée par @seo |
@seoSchema($post) | Uniquement le <script> JSON-LD, valide dans le head ou le body |
Toutes acceptent la même expression ($model, $route, $locale) que @seo, ou aucun argument pour la page courante.
Variantes hreflang
Les modèles utilisant HasSEO peuvent fournir leurs liens hreflang directement au résolveur :
public function getSEOAlternates(): ?array
{
return [
['hreflang' => 'en', 'href' => route('posts.show', ['locale' => 'en', 'post' => $this])],
['hreflang' => 'it', 'href' => route('posts.show', ['locale' => 'it', 'post' => $this])],
];
}Utilisez des URL absolues. @seo($post) résout ces entrées et produit pour chacune un <link rel="alternate" hreflang="..." href="...">. Les codes sont d'abord normalisés au format BCP 47 (it_IT → it-IT). Les politiques seo.hreflang peuvent ajouter une référence à la page elle-même et un x-default. L'audit gratuit signale les entrées invalides, en double ou sans autoréférence. Voir contenu multilingue.
Échappement et sécurité
Les valeurs textuelles sont échappées avec e(). Le JSON-LD est encodé avec JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP. Un </script> présent dans un contenu utilisateur ne peut donc pas fermer prématurément l'élément script.