
Ergänze in der Datei functions.php deines Themes einen Filter auf parse_query, der jede Suchanfrage in eine 404 verwandelt, und einen Filter get_search_form, der eine leere Zeichenkette zurückgibt; entferne außerdem Widget und Suchblock. Der vollständige Code, getestet mit WordPress 7.1, steht im Artikel; ein Plugin ist nicht nötig.
Eine Visitenkartenseite mit fünf Seiten, eine One-Page-Website, ein Portfolio: Die WordPress-Suche bringt dort nichts, und ihr Formular steht dem Theme im Weg. Schlimmer noch, die Ergebnisseite gibt es auch ohne Formular, unter der Adresse /?s=mot, und sie zeigt eine leere Seite oder eine Liste von Inhalten, die du gar nicht hervorheben wolltest. So schaltest du die Suche in WordPress vollständig ab, ohne Plugin, mit einem Ausschnitt für functions.php.
Warum die Suche abschalten
- Auf einer kleinen Website ist sie nutzlos: Alles ist mit einem Klick über das Menü erreichbar.
- Sie erzeugt wertlose Ergebnisseiten, die Bots mit beliebigen Wörtern abrufen können, was Serverressourcen verschwendet und Müll-URLs entstehen lässt.
- Das vom Theme aufgezwungene Formular passt oft nicht in das Layout.
Der vollständige Code für functions.php
Er gehört in die Datei functions.php deines Child-Themes (oder in ein kleines eigenes Plugin, damit er einen Theme-Wechsel überlebt). Jeder Block schließt eine andere Tür.
<?php
/**
* Schaltet die WordPress-Suche im öffentlichen Bereich ab.
*/
// 1. Jede Suche über die URL (/?s=mot oder /search/mot/) wird zu einer 404-Seite.
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. Das Suchformular des Themes wird nicht mehr angezeigt.
add_filter( 'get_search_form', '__return_empty_string' );
// 3. Das klassische Such-Widget wird entfernt.
add_action( 'widgets_init', function () {
unregister_widget( 'WP_Widget_Search' );
}, 11 );
// 4. Der Block „Suche“ des Editors verschwindet aus dem Inserter.
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. Der REST-Endpunkt der Suche ist geschlossen.
add_filter( 'rest_endpoints', function ( array $endpoints ) {
unset( $endpoints['/wp/v2/search'], $endpoints['/wp/v2/search/(?P<id>[\d]+)'] );
return $endpoints;
} );Was jeder Block macht:
- Die Abfrage. Bei
parse_querywird die Hauptabfrage, wenn sie im öffentlichen Bereich eine Suche ist, mitset_404()und dem passenden HTTP-Code in eine 404 verwandelt.is_admin()lässt die Suche im Backend unangetastet;is_main_query()verhindert, dass Nebenabfragen von Erweiterungen betroffen sind. - Das Formular.
get_search_form()ist die Funktion, die Themes zum Anzeigen des Formulars aufrufen; der Filter lässt sie eine leere Zeichenkette zurückgeben. - Das Widget der klassischen Themes.
- Der Block der blockbasierten Themes. Der Filter bekommt entweder
true(alle Blöcke erlaubt) oder eine Liste: Im ersten Fall baut man die vollständige Liste neu auf, bevor mancore/searchdaraus entfernt. - Die REST-API.
/wp-json/wp/v2/search?search=motliefert von nun an einen Fehlerrest_no_routestatt einer Ergebnisliste.
Prüfen
Drei Anfragen genügen, im Browser oder mit 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":"Es wurde keine Route gefunden, die zur URL und zur Anfragemethode passt."…
curl -s "https://exemple.fr/" | grep -c 'role="search"'
# 0: kein Formular mehr auf der Seite (wenn das Theme über get_search_form geht)Im Backend müssen die Suche nach Beiträgen, Seiten und Medien weiterhin funktionieren.
Wenn das Theme sein eigenes Formular ausgibt
Manche Themes schreiben das Formular direkt in ihre Templates (header.php, searchform.php), ohne über get_search_form() zu gehen. Der Filter wirkt sich dann nicht auf die Anzeige aus. Zwei Möglichkeiten: das betroffene Template in einem Child-Theme überschreiben oder das Formular übergangsweise per CSS ausblenden:
.search-form,
form[role="search"] {
display: none;
}Das CSS versteckt nur: Die Sperre für /?s= durch den ersten PHP-Block bleibt unverzichtbar.
Variante: ?s= per .htaccess umleiten
Wenn du lieber keine 404 ausliefern, sondern zur Startseite umleiten willst, erledigt das eine Apache-Regel, noch bevor WordPress läuft. Sie ist auf die Wurzel der Website begrenzt, damit die Suche im Backend (wp-admin/edit.php?s=…) unberührt bleibt.
# Vor dem Block # BEGIN WordPress einfügen
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)s= [NC]
RewriteRule ^$ /? [R=301,L]Das abschließende ? leert den Query-String der Umleitung. Diese Regel und der PHP-Code schließen sich nicht aus: Die erste erspart dem Server, WordPress auszuführen, der zweite bleibt der eigentliche Schutz, auch für Permalinks der Form /search/mot/.
Und das Plugin Disable Search?
Es gibt es, und es macht dasselbe. Auf Gekkode lautet die redaktionelle Linie, keine Erweiterung für etwas hinzuzufügen, das ein Theme in dreißig Zeilen erledigt: eine Abhängigkeit weniger, die aktualisiert werden will, und ein Verhalten, das du in deinem eigenen Code nachlesen kannst. Wenn du mehrere Websites ohne Child-Theme betreust, bleibt das Plugin eine vernünftige Option.
In dieselbe Richtung gehen den Zugang zum WordPress-Backend einschränken und eine WordPress-Website migrieren: zwei weitere Aufgaben, die ohne Erweiterung gelingen.
Häufige Fehler
is_search() ohne is_admin() zerstört die Suche in den Beitrags- und Medienlisten des Dashboards. Der Code aus diesem Artikel nimmt das Backend aus./?s=mot bleibt für jeden erreichbar, der die URL eintippt. Die Tür schließt der Filter auf parse_query, nicht das Entfernen des Formulars.s= ohne Einschränkung des Pfads leitet auch wp-admin/edit.php?s=… um. Begrenze die Regel auf die Wurzel der Website.get_search_form() nicht benutzt, entfernt der Filter es nicht. Dann musst du das Template des Themes anpassen (am besten in einem Child-Theme).

