Des options de tri pour vos pages d’archive et de taxonomie
Aujourd’hui, nous allons voir comment concevoir un système de filtre d’article, en front-office.
Il permettra aux utilisateurs qui visitent une page d’archive ou de taxonomie d’isoler uniquement les articles qui les intéresse, et de les trier selon leurs propres critères.
Je l’utilise relativement souvent sur les thèmes que je réalise, et particulièrement sur des sites autres que blogs.
Il y a plusieurs méthodes pour réaliser cela, mais celle qui va suivre à la particularité de ne pas dupliquer les urls. Elle ne créer pas de nouvelles ramifications dans la structure du site, et ne dilue pas le « jus » SEO de vos pages.
Et puis elle est simple à utiliser…
Tri d’articles par metadonnée
Pour illustrer la mise en place d’un tel système, je vais prendre pour exemple le site d’une agence immobilière.
Sur la page où sont listés les biens à vendre, il peut-être intéressant de laisser à l’utilisateur le choix :
- d’afficher les maisons à vendre en fonction de leur prix
- de montrer les annonces par ordre de parution
- de les sortir par ordre croissant ou décroissant
On imagine que les annonces correspondent à un Custom Post Type, et que le prix de chaque bien y est enregistré en tant que meta-donnée. La date de parution, elle, renvoie nativement à la publication de l’article WordPress.
On va mettre en place notre système de tri en trois étapes :
- créer un formulaire pour l’utilisateur
- retenir ses préférences d’affichage dans une variable de session
- puis modifier la requête en fonction de ses choix
Les codes qui vont suivre doivent être déposés dans le fichier functions.php de votre thème.
Un formulaire pour organiser l’affichage de vos contenus.
Pour permettre à l’internaute de choisir un mode d’affichage, nous allons concevoir un formulaire.
Vous allez probablement devoir le réutiliser à plusieurs endroits de votre thème. Il est donc préférable de le créer dans une fonction que nous appellerons là où il faut (dans la page d’archive, de taxonomie…).
Il n’est pas nécessaire de préciser l’action du formulaire ; lors de sa soumission, il se rechargera sur la même page.
Le formulaire n’a besoin que de deux entrées :
- post-order-by : un select pour trier par date ou par prix
- post-order : un select pour afficher par ordre croissant ou décroissant
Le changement de valeur d’un de ces éléments soumet automatiquement le formulaire grâce à l’attribut onchange= »this.form.submit() ».
Il faut maintenant exécuter la fonction switcher_session() dans le template d’archive de notre custom post type, et éventuellement de taxonomie. Je vous suggère d’appeler fonction entre if( have_posts() ) et while( have_posts() ).
Si on visite la page, le formulaire y apparait maintenant.
Un fois qu’il sera validé, il faudra sauvegarder les informations quelque part. Le plus logique dans le cas présent est de les stocker dans la variable de session. Ainsi les informations seront isolées pour chaque utilisateur et persisteront tant qu’il ne ferme pas son navigateur.
Enregistrer les options dans la session
Pour créer et mettre à jour une variable de session, il faut lancer une fonction qui s’exécutera lors de l’initialisation de WordPress.
On utilise donc le hook init.
L’enregistrement des choix de l’utilisateur se fait en trois étapes :
- on ouvre une session
- si le formulaire a été soumis, on met à jour la variable
- si la variable n’existe pas (et que donc le formulaire n’a pas encore été soumis), on créer la variable avec une valeur par défaut
Il est important de s’arranger pour que les valeurs passées en post ne soient pas ajoutées telles quelles dans la variable. Simplement pour des raisons de sécurité…
WordPress à un comportement particulier avec les variables de session ; le code présenté aura besoin, dans certains cas normalement assez rares, d’être adapté.
À ce stade, les choix de l’utilisateur sont enregistrés. Par contre ils ne s’afficheront pas dans le formulaire qui vient de se recharger.
Il faut les récupérer via la session puis utiliser la fonction selected() de WordPress pour sélectionner l’option en cours.
Altérer la requête WordPress
Maintenant l’étape ultime : overider la requête.
Grâce au hook pre_get_posts, c’est quelque chose d’assez simple à faire.
Il faut y exécuter une fonction qui va filtrer les argument de WP_Query.
Tout d’abord on vérifie qu’il s’agit de la bonne requête à surcharger (page d’archive du post type ciblé, requête principale en front), puis on va chercher nos valeurs sauvegardées en session.
La variable $q représente la WP_Query ; on utilise la méthode set() pour en redéfinir certaines parties.
Si la valeur de post-order-by est « price », alors on ajoute à la requête les conditions meta_key = _price (qui correspond à la metadonnée) et orderby = meta_value_num.
Si post-order-by est défini à date, alors nous n’avons rien à faire car WordPress tri les articles par date par défaut.
Puis on défini order selon la valeur de post-order.
Il n’y a pas besoin de tester nos variables de session, puisque l’on sait qu’elles ont été correctement définies lors de l’init.
Le code complet
Notre système de tri est maintenant pleinement fonctionnel 🙂
Re-voici le code dans son intégralité :
D’autres possibilités de filtres
Tout fonctionne, mais aurait pu aller beaucoup plus loin…
Filtrer les articles par terme de taxinomie
Reprenons notre exemple d’agence immobilière, et imaginons que l’on veuille filtrer les biens selon qu’ils soient des appartements, des villas, des maisons…
Il suffit simplement d’ajouter un select dans le formulaire, et d’y lister les termes de la taxonomie genre-bien (la taxonomie relative à nos type de biens).
Ensuite on sauvegarde les entrées souhaitées, en vérifiant ce qui a été saisi :
… puis on personnalise la requête.
Si plusieurs requêtes de taxonomie doivent être réalisées, il faudra composer la tax_query en plusieurs étapes (mais ici ce n’est pas le cas 😉 )
Filtrer les contenus en fonction de metadonnées
On continu avec notre agence immobilière !
Chaque bien de l’agence possède (ou non) certains équipements. Certains clients seront intéressés uniquement par les habitations qui comportent une piscine, une cuisine aménagée ou autre…
Ces différents équipements ont été entrés dans WordPress en tant que meta-donnés des hébergements.
Nous allons ajouter une checkbox « piscine » dans le formulaire :
Vu que la checkbox qui ne sera pas cochée ne sera pas soumise en post, il faut insérer un input hidden avec le même name juste avant, mais avec une valeur différente.
Ensuite on sauvegarde l’option dans une session.
… et pour finir on défini une nouvelle condition dans le pre_get_posts qui ajoutera une meta_query, si besoin.
Voilà, vous pouvez maintenant réaliser vos propres filtres d’article en front office.
Le gros avantage de cette méthode est qu’elle ne créer pas plusieurs pages avec des contenus quasi-similaires. C’est particulièrement intéressant au niveau de l’optimisation pour les moteurs de recherche.
N’hésitez pas à me dire ce que vous en pensez !
Ce que j’aime est que cela peut servir dans d’autres contextes également.
En revanche toute la documentation que j’ai pu lire sur les sessions dans WordPress recommande cet ajout dans le hook init :
Il faudrait aussi un
session_destroy ();
sur les hookswp_logout
etwp_login
au cas où un utilisateur se logue avec différents identifiants.Pour le session_start(), il est indispensable sinon la variable de session ne fonctionne pas.
Par contre je ne me suis pas embêté ici avec le session_destroy()…
La plupart de ces systèmes (dont les taxonomies WordPress, ou les archives datées) créent des pages avec des URLs différents et des contenus très similaires (mêmes articles et mêmes descriptions).
Alors qu’un système de session, lui, ne créer pas de nouvelles URLs. C’est juste ça.
J’avais testé avec un système de session de proposer sur une home des contenus selon un profil pré-déterminé, le moteur visitant celui par défaut.
En gros je chargeais les catégories selon les profils. Il me reste plus qu’à intégrer ces filtres et la personnalisation est complète et propre.
Avec ce code le filtre est généré à la volée, le moteur n’ayant pas de session (fin…) il y verra un seul et unique site et contenu. Dites si je me trompe !
J’ai bien aimé le check :
( in_array( $_POST[ ‘post-genre’ ], wp_list_pluck( ‘slug’, $terms ) ) )
Un peu noob, mais j’aurais ajouté un wp_nonce_field dans le formulaire .. Bonne ou mauvaise idée ?
Autre question, y aurait-il un intérêt à passer les paramètres en paramètre WP ? En tout cas, j’ai cherché à le faire pour un cas perso .. sans succès !!
Le check de sécurité, c’est Julio de Boite a Web qui me l’a montré. Très pratique, et pas très long, j’aime bien aussi…
Pour le nonce field, ici je ne suis pas persuadé qu’il y en ai besoin : quel est le risque ? Une CSRF pour prendre le contrôle du tri des articles d’un internaute ? 😛
Mais après, oui, c’est possible.
On pourrai passer les paramètres à WP, mais dans des cas plus complexes, et cela sera le thème d’un futur article 🙂
J’essayais de faire en sorte que l’utilisateur puisse sélectionner plusieurs checkbox de métadonnés à la fois pour la recherche. Pourriez-vous m’aiguiller vers une solution ?
Merci !!!
$q->set( ‘orderby’, ‘meta_value_num’);
j’ai du zapper un truc..
Merci et bonne continuation
Par contre, j’ai une petite question : je souhaiterais initialiser tous les paramètres appliqués d’une seule traite (plusieurs taxo filtrées) pour avoir une page clean à la demande même si les données s’effacent une fois le navigateur fermé. Comment puis-je procéder ?