Tout savoir sur WordPress

Mettre en place un filtre de recherche en fonction d’une catégorie ou d’un custom post type

Cette astuce montre la démarche à suivre pour créer un formulaire de recherche avec un filtre par catégorie ou par Custom Post Type.

Si vous souhaitez permettre à vos visiteurs de faire une recherche en fonction d’une catégorie ou d’un Custom Post Type via une liste déroulante, alors wp_dropdown_categories() ne conviendra pas.

La solution consiste à créer un formulaire de recherche et de modifier le comportement des résultats à l’aide du filtre pre_get_posts.

Ajout du formulaire de recherche

Pour commencer, on doit créer notre propre formulaire de recherche comme ci-dessous :

<form method="get" id="searchform" action="<?php echo esc_url( home_url( '/' ) ); ?>">
    <p>
	<label for="s">Mots clés :
	<input type="text" name="s" id="s" />
   </p>
   <p>
	<label for="myselect">Catégorie :
	<select id="myselect" name="search">
		<option value="">Tout le site
		<option value="cat1">Catégorie 1
		<option value="cat2">Catéogorie 2
		<option value="book">Livres
	</select>
   </p>
   <p>
	<input type="submit" class="submit" name="submit" id="searchsubmit" value="Valider" />
   </p>
</form>

Dans notre exemple, cat1 et cat2 sont des catégories, tandis que book est un Custom Post Type.

Modifier les résultats de la recherche

Ensuite pour modifier les résultats retournés pour la recherche, il suffit d’ajouter le code suivant dans votre fichier functions.php présent à la racine de votre thème :

add_filter('pre_get_posts','custom_search_filter');

function custom_search_filter( $query ) {
	
   // Si on est entrain de faire une recherche
   if ( $query->is_search ) {

	switch( $_GET['search']  ) {

	    case 'book':
		$query->set( 'post_type', 'book' );
		break;

	    case 'cat1':
		$query->set( 'category_name','cat1' );
		break;

	    case 'cat2':
		$query->set( 'category_name','cat2' );
		break;
	}
    }
    return $query;
}

Vous voilà désormais avec une recherche fonctionnant avec un filtre par catégorie et par Custom Post Type.

Cet article a été publié il y a 2279 jours - Il n'est peut être plus à jour !

Article écrit par Rtransat

45 Commentaires

  1. pouvez-vous m’aider à faire ceci mais plutôt à mettre en place un filtre de recherche en fonction d’un lieu et non d’une catégorie.

  2. A quoi correspond ce « lieu » ? un champ personnalisé ? Si le « lieu » n’est pas une catégorie, l’astuce sera plus complexe.

  3. Merci pour la réponse, mais je ne suis pas plus avancé :/ Ce lieu est stocké où ? Dans un champ personnalisé ? Une catégorie ? etc…

  4. Désolé d’insisté, mais c’est quoi cp_country ? Le champ d’une autre table, un champ personnalisé ?

  5. Bonjour, voila un le même type de recherche que je cherche à effectuer.
    Le cp_country est un meta_key de la table wp_postmeta.

  6. @Tilap : Il me semble que l’on peut s’en passer étant donné que l’on check si on se trouve sur une recherche avec $query->is_search. Si $_GET[‘search’] n’existe pas, on ne passerai pas avec la condition du $query->is_search.

    A tester tout de même.

  7. Si ça ne fonctionne pas, c’est que vous avez mal configuré quelque chose.

    Pouvez-vous nous copier votre via pastebin.com ?

  8. Merci pour cette réponse rapide. Je suppose que vous voulez que je copie le code? Je peux le faire mais je vous assure que c’est un copié-collé de ce qui est au dessus dans l’article car j’ai un Custom_Post_type book comme dans l’exemple. Est ce que ca peut etre du à la mise à jour de wordpress 3.5? Mon array $_GET est vide !!!

  9. Non, WP 3.5 à rien à voir avec ce code.

    Je pense que le mieux est de nous fournir 2 liens pastebin avec le code html du formulaire et la partie PHP du fichier functions.php.

  10. Remarque : Si j’effectue « $query->set(); » en dehors du switch directement dans le if, cela fonctionne ? Mon problème vient vraiment de mon $_GET je crois.. Merci encore une fois pour votre aide

  11. J’ai bien les variables de mon url de départ mais j’ai une redirection 301 (vers /site/search/keyword). Est ce que c’est à ce moment la que je perds mes variables $_GET? Et si oui, comment je peux faire?

  12. De la réécriture d’url, je pense.. J’ai ceci : « /site/?s=keyword&search=book&submit=Recherche » qui devient « /site/search/keyword » .

  13. @Mikl : Dans ce cas c’est tout à faire normal que la variable $_GET[‘search’] ne soit plus disponible car elle ne doit pas passé dans la réécriture.

    C’est quoi le code qui a permit de faire cette redirection ?

  14. Merci pour le temps passé sur mon cas. Oui, c’est bien ce qui me semblait mais j’espérais que la fonction fasse le travail avant la redirection.
    Je ne sais pas trop d’ou vient cette réécriture, ça doit être les permaliens de mon thème et de wordpress. J’ai ceci dans mon .htaccess :
    # BEGIN WordPress

    RewriteEngine On

    RewriteBase /site/
    RewriteRule ^index.php$ – [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /site/index.php [L]

    # END WordPress

  15. Ahahah je viens de trouver le problème grâce à ton aide précieuse. J’utilise le Thème Roots et j’ai trouve ceci dans le fichier cleanup.php :

    /**
     * Redirects search results from /?s=query to /search/query/, converts %20 to +
     *
     * @link http://txfx.net/wordpress-plugins/nice-search/
     */
    function roots_nice_search_redirect() {
      if (is_search() && strpos($_SERVER['REQUEST_URI'], '/wp-admin/') === false && strpos($_SERVER['REQUEST_URI'], '/search/') === false) {
        wp_redirect(home_url('/search/' . str_replace(array(' ', '%20'), array('+', '+'), urlencode(get_query_var('s')))), 301);
        exit();
      }
    }
    
    add_action('template_redirect', 'roots_nice_search_redirect');
    
    /**
     * Fix for get_search_query() returning +'s between search terms
     */
    function roots_search_query($escaped = true) {
      $query = apply_filters('roots_search_query', get_query_var('s'));
    
      if ($escaped) {
        $query = esc_attr($query);
      }
    
      return urldecode($query);
    }
    
    add_filter('get_search_query', 'roots_search_query');
    
    /**
     * Fix for empty search queries redirecting to home page
     *
     * @link http://wordpress.org/support/topic/blank-search-sends-you-to-the-homepage#post-1772565
     * @link http://core.trac.wordpress.org/ticket/11330
     */
    function roots_request_filter($query_vars) {
      if (isset($_GET['s']) && empty($_GET['s'])) {
        $query_vars['s'] = ' ';
      }
    
      return $query_vars;
    }
    
    add_filter('request', 'roots_request_filter');
    
    /**
     * Tell WordPress to use searchform.php from the templates/ directory
     */
    function roots_get_search_form() {
      locate_template('/templates/searchform.php', true, true);
    }
    
    add_filter('get_search_form', 'roots_get_search_form');
    

    Reste plus qu’à trouver une solution propre :)

  16. Bonjour, et merci pour cette astuce bien pratique !
    Elle fonctionne si bien que j’ai voulu m’en servir pour filtrer par année mes résultats de recherche.
    J’ai suivi le même principe malheureusement, le filtre ne filtre pas et sort quand même les articles de toutes les années correspondants à ma recherche … Pourtant le paramètre ‘year’ prend bien la valeur voulue dans la requête. Auriez-vous une idée ?

  17. Bonjour Jonathan.
    Je suis en train de réaliser un WordPress pour mon entreprise. Malheureusement je suis une grosse novice en programmation et j’ai absolument besoin d’un filtre qui trierait les recherches d’évènements par lieux (ville) grâce à un menu déroulant.
    Le nom des villes se trouve dans le texte corps de l’évènement et pour gérer mes events j’utilise all-in-one event (car il contenait d’office le filtre par catégorie d’évènements, ce dont j’avais besoin aussi.
    Mes questions sont donc: est-ce que cette manoeuvre est faisable? Si oui il y a une solution pour l’intégrer plutôt facilement dans mon WP? (j’ai commencé à programmé un peu hier et avant hier mais rien d’exceptionnel).
    Merci pour ton aide :)

  18. @ Gwennite: Je ne connais pas du tout le plugin all-in-one event. Je ne vais pas pouvoir être d’une grande aide :/

  19. Bonsoir,

    Je voudrais savoir à quel endroit faut-il mettre le code « Ajout du formulaire de recherche »

    Merci

  20. @ sylvainbr: C’est ça à vous de décider. Ça peut-être dans votre header ou votre sidebar. En gros, c’est à l’endroit où vous souhaitez l’afficher.

  21. Bonjour,

    J’ai un gros problème, j’ai voulu utiliser cette astuce sur le thème que je développe
    en local sur wamp, je n’y suis pas parvenu alors j’ai effacé le formulaire de recherche de mon header et la fonction dans fonction.php pour faire machine arrière.
    Malheureusement à présent il m’apparaît dans l’admin de wordpress ce message  » Warning: call_user_func_array() expects parameter 1 to be a valid callback, function ‘custom_search_filter’ not found or invalid function name in C:wampwwwwordpresswp-includesplugin.php on line 507″

    Je suis un peu d’espéré, pourriez vous m’aider?
    Je vous remercie d’avance.

  22. @Pierre: Vous avez oublié de supprimer cette ligne ;)

    add_filter('pre_get_posts','custom_search_filter');
  23. J’ai essayé ce code et j’ai l’erreur suivante quelque soit la recherche:

    Accès interdit!

    Vous n’avez pas le droit d’accéder à l’objet demandé. Soit celui-ci est protégé, soit il ne peut être lu par le serveur.

    Si vous pensez qu’il s’agit d’une erreur du serveur, veuillez contacter le gestionnaire du site.
    Error 403
    127.0.0.1
    02/02/2014 23:22:38
    Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1

    ————————————–

    D’autre part je ne sais pas ci c’est le bon code que je dois utiliser.

    j’ai utiliser la fonction ‘function register_documentation’ pour créer un custom poste type.

    Je voudrais que ma recherche ne puisse pas rechercher dans ce custom poste type.

    Est-ce possible de faire cela?

  24. Je m’étais rendu compte de cet oubli quelques temps après l’envoi de mon message de désespoir.

    Quel âne je suis!

    En tous cas merci à vous de m’avoir répondu.
    Votre site est fantastique!

  25. je serai intéressé pour faire une recherche multi critère, c’est à dire d’un côté avec les catégories, et d’autres part avec les départements de France ..

    j’ai testé votre code, question affichage, c’est nickel, par contre, en testant les recherches, rien ne fonctionne … que dois je modifier dans functions ?

  26. @nemesis2508 : Le code est à adapter en fonction de vos catégories. Ne les connaissant pas, je ne peux pas vous aider.

  27. Vraiment de bonnes ressources, comme d’habitude. Une idée de comment utiliser les filtres par catégorie en restant sur la même page ?
    Par exemple on a une page avec tous nos articles, et on a un menu déroulant avec nos différentes catégories et lorsque l’on en sélectionne une, les articles de la catégorie sélectionnée restent, les autres disparaissent .

  28. Bonjour,

    Tout d’abord merci pour ton article qui m’a fait avancer rapidement dans la création de mon moteur de recherche multicritère.

    J’ai cependant 1 question :
    j’ai 3 catégories dans mon moteur : département, types de locaux, location / vente.
    Quand je lance une recherche du type :
    Var + bureaux + location, la page de résultat me renvoie tous les articles ayant au moins une de ces catégories. Un article du département du Vaucluse va donc ressortir s’il est présent dans la catégorie « location ».

    Comment fait-on pour que le moteur prenne en compte le choix des 3 catégories et que le ou les filtre(s) se fassent ?

    Je précise que j’ai seulement des notions en programmation, c’est donc peut-être une broutille pour les experts :-).

    Merci d’avance

  29. J’ai testé cela marche bien chez moi lorsqu’il y a une catégorie !
    Par contre est-ce possible d’avoir plusieurs filtres ? exemple filtre n°1 les âges, filtre n°2 les activités ?

  30. Bonjour Jonathan,

    Pour palier à la recherche des fichier PDF maintenant j’utilise le plugin Google searche sur notre site. A priori il n’est pas possible d’utiliser la recherche dans des catégorie comme votre code le permet. A votre avis est-il possible de le faire ou pas.

  31. Bonjour,

    merci pour ce super code ! c’est exactement ce que je recherchais.

    Par contre à la place de « tout le site » je voudrais mettre « tous les prestataires » et si la personne ne choisis pas de catégorie, la recherche se fasse sur tous les custom poste types

    auriez vous une idée ?

    Merci d’avance

adipiscing quis, commodo Sed commodo nunc quis efficitur. eleifend