Des pages de présentation pour vos archives
Les custom post types de WordPress sont une fonctionnalité qui nous permet de créer, via des thèmes ou des plugins, de nouveaux types de contenu. Ces contenus sont accessibles sur le site via des pages de taxonomie, d’archives ou singulières.
Ma grosse frustration est de ne pas pouvoir nativement ajouter d’introductions sur les pages d’archives des Custom Post Types, comme on peut le faire avec un terme sur une page de taxonomie.
L’objet de cet article est de voir comment créer des pages de présentation d’archives, et comment les exploiter à travers nos templates.
Une metabox pour associer une page et une archive
Pour lier une page de description et une archive, nous allons concevoir une metabox. Elle nous permettra, dans le menu d’édition des pages, d’indiquer que telle page sert à la présentation de tel custom post type. La meta donnée qui fera la liaison aura pour clef _archive_page.
Il faut, pour commencer, ajouter une nouvelle meta box en copiant le code suivant dans le fichier functions.php de votre thème.
Nous venons d’ajouter une nouvelle boîte, en haut à droite du menu d’administration des pages.
Construire la boîte qui liste les types de contenus
Pour l’instant cette boîte fait tout planter, car nous n’avons pas encore créer la fonction « archive_page » dont elle a besoin pour se construire.
Juste en dessous du code précédent, on ajoute cette nouvelle fonction.
Cette fonction liste les custom post types de WordPress dans un sélecteur.
Dans get_post_types, les options show_ui et _builtin servent à préciser que l’on ne souhaite pas ressortir les post types natifs de WordPress, ni les types de contenus privés.
Il ne faut pas oublier de rajouter une option « Aucune » avec une valeur vide, pour les pages normales.
La fonction selected servira, après la sauvegarde, à réassigner la valeur enregistrée dans _archive_page à l’option du select correspondante.
Sauvegarder la liaison entre la page et le custom post type
Pour finir la metabox, il ne nous reste plus qu’à sauvegarder la metadonnée.
On ajoute, grâce au hook save_post, une fonction au moment de la sauvegarde de la page.
S’il s’agit d’une sauvegarde automatique, ou si le nonce n’est pas vérifié on arrête tout… sinon on continue.
La sauvegarde de cette metabox est un peu particulière car il ne faut pas que deux pages présentent le même type de contenu.
On commence donc par rechercher dans notre base de données toutes les autres pages associées à la même archive, et on supprime leur meta _archive_page.
Il ne reste plus qu’à sauvegarder notre meta.
La fonction qui affiche la présentation
Nous avons maintenant tout ce qu’il faut pour afficher le contenu de la page de description sur la page d’archive. Y’a plus qu’à…
Même si vous pouvez directement faire une requête dans vos templates d’archive, je vous conseille plutôt de créer une fonction dans functions.php, et de l’exécuter dans ces templates.
Voici le code :
On commence par récupérer l’objet appelé dans la requête (un post type). Ensuite on fait une requête avec une meta_query pour récupérer la page liée.
Enfin, on boucle sur cette requête (enfin, on ne boucle pas vraiment puisqu’il n’y a qu’un seul résultat) et on affiche ce que l’on souhaite.
On peut placer la fonction presentation_archive() où l’on veut, tant que c’est sur le template de l’archive.
Réécrire le permalien de la page de description
La page utilisée en tant que description s’affiche bien à présent lorsque l’on visite la page d’archive. Mais cette page continue d’exister, avec sa propre URL, ailleurs sur le site.
Et si on se greffait sur la fonction get_permalink afin de transformer l’URL de la page de présentation en URL de l’archive ?
Nous allons faire d’une pierre deux coups 🙂
- En supprimant les éventuelles occurences à l’URL de la page de description, partout sur le site (dans le thème, les menus, les sitemaps, les rss…)
- En permettant d’utiliser cette page pour cibler la page d’archive, comme dans les menus par exemple (où l’on ne peut pas nativement cibler une page d’archive)
Utile n’est-ce pas ? Voici le code :
Une redirection si l’on essaye d’accéder directement à la page
Le site ne comporte plus de lien vers la page de description de l’archive, mais on peut toujours y accéder directement si l’on connait l’URL.
Pour éviter ça il faut mettre en place une redirection 301, de façon automatique.
Au moment du template_redirect, si le contenu chargé est une page, et si elle comporte une meta donnée _archive_page, alors on la redirige. Une redirection 301 est définitive et fera rapidement comprendre aux moteurs de recherche que la page recherchée a changée d’adresse.
Les classes des menus
En substituant l’archive à sa description, les entrées du menu vers la page d’archive cesseront de se voir appliquer les éventuelles classes current-menu-item et current-menu-ancestor.
Pour rétablir ce comportement, il faut appliquer un filtre sur nav_menu_css_class qui est utilisé dans le walker wp_nav_menu.
On y compare l’objet du menu et la page courante. En cas de correspondance on ajoute la classe qui va bien.
Le système dans son intégralité
Voilà, c’est fini ! Revoici le code dans son intégralité :
Vous pouvez, si vous le souhaitez, prendre ce code et le lâcher dans un fichier du dossier mu-plugin. Il ne restera plus qu’à appeler la fonction dans votre template d’archive.
Une variante…
Ces lignes de code peuvent être insérées au choix dans le fichier functions.php, dans un plugin ou un mu-plugin. Peu importe…
Pour établir la liaison entre une page de contenu et une page d’archive, il y a deux façons de procéder :
- passer par une meta donnée pour « dire » que telle page présente telle archive
- passer par une option WordPress pour dire que telle archive souhaite être présentée par telle page
Chaque méthode a ses avantages ; pour des raisons de souplesse j’ai préféré utilisé la première.
Mais rien n’empêche d’utiliser l’autre technique 😉
Une alternative, bien moins pratique, serait d’utiliser le champs « description » de
register_post_type()
, mais cela pose plein de contraintes.Sinon, il ne serait pas plus avisé d’utiliser le paramètre « has_archive » au lieu de « show_ui » pour le
get_post_types()
? (ok, ça revient presque au même)Dernier point, concernant ta fonction
my_save_post()
, je note quelques erreurs et failles de sécurité. De plus, il y a bien plus pratique quewpdb
+foreach
selon moi. Je te propose ça plutôt (non testé) : http://pastebin.com/ZJhFGB2DT’en dis quoi ? 🙂
A++
get_post_types()
, je n’avais pas vu regardé le détail de la fonction. Le codex ne le mentionne pas mais on peut lui passer les mêmes paramètres que register_post_type, et la fonction ressortira les post_type correspondants.Alors je ne connaissais pas du tout
delete_metadata()
, et ton code fonctionne très bien ! Pratique pour supprimer les occurrences d’une même meta indifféremment l’ID de l’objet auquel elle est rattachée 🙂 Merci !Tu as raison, je devrais vérifier la valeur de _archive_page avant la sauvegarde. Habituellement je le fais à l’affichage, mais pas ici…
Par contre je n’ai pas compris l’intérêt de tester que
$_POST[ 'post_id' ]
soit bien un entier. Si on essaye de faire une injection (ou autre) dessus, lecheck_admin_referer()
va stopper le tout, non ?Merci pour ce commentaire qui me permet de peaufiner le système !!
Nan mais ok, je comprend, je corrige 🙂
( $_post_ID = (int) $_POST[ 'post_ID' ] )
, le cast est simplement une habitude que j’ai prise (regard accusateur vers ) et sa présence dans leif
permet aussi de vérifier que la valeur retournée n’est pas 0.PS : il reste une typo (que j’avais corrigée dans mon pastebin :p), le
return $post_id;
devrait êtrereturn $post_ID;
😉Merci pour se script.
Mais comment passer par une meta donnée pour « dire » que telle page présente telle archive.
Car j’ai créé un custom post type dans le back office.
Quel code à mettre dans la page où je veux afficher les données liés à mon custom post type.
C’est exactement ce que je cherchais pour un projet.
#laclasse #lesbonstuyauxwp
Thx!