WordPress-Suche deaktivieren ohne Plugin (functions.php, ?s=, REST)

Der vollständige Code, um die WordPress-Suche ohne Plugin abzuschalten: bei ?s=-URLs eine 404 ausliefern, Formular, Widget und Suchblock entfernen, den REST-Endpunkt schließen, dazu die .htaccess-Variante.

WordPress-Suche deaktivieren: per Code-Schnipsel oder Plugin
Schnelle Antwort

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.

functions.php
<?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:

  1. Die Abfrage. Bei parse_query wird die Hauptabfrage, wenn sie im öffentlichen Bereich eine Suche ist, mit set_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.
  2. 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.
  3. Das Widget der klassischen Themes.
  4. 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 man core/search daraus entfernt.
  5. Die REST-API. /wp-json/wp/v2/search?search=mot liefert von nun an einen Fehler rest_no_route statt einer Ergebnisliste.

Prüfen

Drei Anfragen genügen, im Browser oder mit curl:

bash
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:

css
.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.

.htaccess
# 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/.

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

Auch die Suche im Backend blockieren Ein Test mit 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.
Das Formular entfernen und die URL vergessen Das Formular ist nur eine Tür: /?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.
Eine .htaccess-Umleitung für die ganze Website Eine Regel auf s= ohne Einschränkung des Pfads leitet auch wp-admin/edit.php?s=… um. Begrenze die Regel auf die Wurzel der Website.
Ein Theme, das sein eigenes Formular ausgibt Wenn das Theme get_search_form() nicht benutzt, entfernt der Filter es nicht. Dann musst du das Template des Themes anpassen (am besten in einem Child-Theme).

WordPress

Damien Flandrin Webentwickler seit 2010, Gründer von Gekkode und Email Impact. Jeder Artikel wird vor der Veröffentlichung an einem echten Projekt getestet. Kontakt
Newsletter

Neue Tests, Tutorials und Projekte, per E-Mail.

Reproduzierbare Tests, versionierter Code, datierte Ergebnisse. Niemals Spam.