
Ajoutez dans le fichier functions.php de votre thème un filtre sur parse_query qui transforme toute requête de recherche en 404, un filtre get_search_form qui renvoie une chaîne vide, et retirez le widget et le bloc de recherche. Le code complet, testé sur WordPress 7.1, est dans l’article, aucun plugin n’est nécessaire.
Un site vitrine de cinq pages, un site one-page, un portfolio : la recherche WordPress n’y sert à rien, et son formulaire encombre le thème. Pire, la page de résultats existe même sans formulaire, à l’adresse /?s=mot, et elle expose une page vide ou une liste de contenus que vous ne vouliez pas mettre en avant. Voici comment désactiver complètement la recherche dans WordPress, sans plugin, avec un extrait pour functions.php.
Pourquoi désactiver la recherche
- Elle est inutile sur un petit site : tout est accessible depuis le menu en un clic.
- Elle produit des pages de résultats sans valeur, que des robots peuvent solliciter avec n’importe quel mot, ce qui gaspille des ressources serveur et crée des URL parasites.
- Le formulaire imposé par le thème n’a souvent pas sa place dans la maquette.
Le code complet pour functions.php
À placer dans le fichier functions.php de votre thème enfant (ou dans un petit plugin maison, pour survivre aux changements de thème). Chaque bloc ferme une porte différente.
<?php
/**
* Désactive la recherche WordPress côté public.
*/
// 1. Toute recherche par URL (/?s=mot ou /search/mot/) devient une page 404.
add_action( 'parse_query', function ( WP_Query $query ) {
if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
return;
}
$query->is_search = false;
$query->set_404();
status_header( 404 );
nocache_headers();
} );
// 2. Le formulaire de recherche du thème n'est plus affiché.
add_filter( 'get_search_form', '__return_empty_string' );
// 3. Le widget de recherche classique est retiré.
add_action( 'widgets_init', function () {
unregister_widget( 'WP_Widget_Search' );
}, 11 );
// 4. Le bloc « Recherche » de l'éditeur disparaît du menu d'insertion.
add_filter( 'allowed_block_types_all', function ( $allowed ) {
if ( ! is_array( $allowed ) ) {
$registry = WP_Block_Type_Registry::get_instance();
$allowed = array_keys( $registry->get_all_registered() );
}
return array_values( array_diff( $allowed, [ 'core/search' ] ) );
} );
// 5. Le point d'accès REST de recherche est fermé.
add_filter( 'rest_endpoints', function ( array $endpoints ) {
unset( $endpoints['/wp/v2/search'], $endpoints['/wp/v2/search/(?P<id>[\d]+)'] );
return $endpoints;
} );Ce que fait chaque bloc :
- La requête. Sur
parse_query, si la requête principale est une recherche côté public, elle est transformée en 404 avecset_404()et le code HTTP correspondant.is_admin()garde la recherche de l’administration intacte,is_main_query()évite de toucher aux requêtes secondaires des extensions. - Le formulaire.
get_search_form()est la fonction que les thèmes appellent pour afficher le formulaire, le filtre lui fait renvoyer une chaîne vide. - Le widget des thèmes classiques.
- Le bloc des thèmes basés sur les blocs. Le filtre reçoit soit
true(tous les blocs autorisés), soit une liste : dans le premier cas, on reconstruit la liste complète avant d’en retirercore/search. - L’API REST.
/wp-json/wp/v2/search?search=motrenvoie désormais une erreurrest_no_routeau lieu d’une liste de résultats.
Vérifier
Trois requêtes suffisent, dans un navigateur ou avec curl :
curl -s -o /dev/null -w "%{http_code}\n" "https://exemple.fr/?s=test"
# 404
curl -s "https://exemple.fr/wp-json/wp/v2/search?search=test" | head -c 120
# {"code":"rest_no_route","message":"Aucune route correspondante à l’URL et à la méthode de requête n’a été trouvée."…
curl -s "https://exemple.fr/" | grep -c 'role="search"'
# 0 : plus de formulaire dans la page (si le thème passe par get_search_form)Dans l’administration, la recherche des articles, des pages et des médias doit continuer de fonctionner.
Si le thème affiche son propre formulaire
Certains thèmes écrivent le formulaire directement dans leurs gabarits (header.php, searchform.php) sans passer par get_search_form(). Le filtre n’a alors aucun effet sur l’affichage. Deux options : surcharger le gabarit concerné dans un thème enfant, ou masquer le formulaire en CSS en attendant :
.search-form,
form[role="search"] {
display: none;
}Le CSS ne fait que cacher : le blocage de /?s= par le premier bloc PHP reste indispensable.
Variante : rediriger ?s= en .htaccess
Si vous préférez ne pas servir une 404 mais renvoyer vers l’accueil, une règle Apache le fait avant même que WordPress ne s’exécute. Elle est limitée à la racine du site pour ne pas toucher la recherche de l’administration (wp-admin/edit.php?s=…).
# À placer avant le bloc # BEGIN WordPress
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)s= [NC]
RewriteRule ^$ /? [R=301,L]Le ? final vide la chaîne de requête de la redirection. Cette règle et le code PHP ne s’excluent pas : la première épargne au serveur d’exécuter WordPress, le second reste la protection de référence, y compris pour les permaliens /search/mot/.
Et le plugin Disable Search ?
Il existe et fait la même chose. Sur Gekkode, la ligne éditoriale est de ne pas ajouter d’extension pour ce qu’un thème peut faire en trente lignes : une dépendance de moins à mettre à jour, et un comportement que vous lisez dans votre propre code. Si vous administrez plusieurs sites sans thème enfant, le plugin reste une option raisonnable.
Dans la même veine, limiter l’accès au back-office de WordPress et migrer un site WordPress sont deux autres opérations qui se font sans extension.
Erreurs fréquentes
is_search() sans is_admin() casse la recherche dans les listes d’articles et de médias du tableau de bord. Le code de l’article exclut l’administration./?s=mot reste accessible à quiconque tape l’URL. C’est le filtre sur parse_query qui ferme la porte, pas la suppression du formulaire.s= sans contrainte de chemin redirige aussi wp-admin/edit.php?s=…. Limitez la règle à la racine du site.get_search_form(), le filtre ne le retire pas. Il faut alors modifier le gabarit du thème (enfant de préférence).

