WordPress: Suchergebnisse nach Inhaltstypen filtern
Um die Suchergebnisse in WordPress übersichtlicher zu gestalten, lassen sich diese mit einigen Anpassungen am Code nach Inhaltstypen filtern.
Die Suchergebnisse in WordPress können besonders bei der Verwendung von verschiedenen Inhaltstypen schnell unübersichtlich werden. Mit Hilfe einer Filter-Funktion nach verschieden Inhaltstypen lässt sich diese Unübersichtlichkeit verhindern und bietet zusätzlich die Möglichkeit einer Priorisierung. Produkte oder Leistungen können beispielsweise höher priorisiert werden als Blog-Beiträge oder Seiten.
Verschiedene Inhaltstypen in WordPress
In WordPress gibt es verschiedene Inhaltstypen (Post Types). In einer Standard-Installation sind das unter anderem Seiten (page
) und Beiträge (post
). Plugins wie beispielsweise die Shop-Erweiterung »WooCommerce« bringen weitere Inhaltstypen wie Produkte, etc. mit, die die Standard-Inhaltstypen erweitern.
Zusätzlich kann das System um eigene Inhaltstypen erweitert werden. Hier spricht man von »Custom Post Types«. Ein nützliches Tool zum Erstellen von »Custom Post Types« findet ihr hier.
Inhaltstypen aus Suche ausschließen
Es kommt vor, dass man nicht immer alle Inhaltstypen auch in der Suche integriert haben will.
Wenn man ein »Custom Post Type« aus der Suche ausschließen will, reicht es in den »Attributen« den Wert exclude_from_search
auf true
zu setzen.
Schwieriger wird es, bei den Standard-Inhaltstypen oder bei Inhaltstypen die von Plugins erstellt wurden, da man hier nicht ohne weiteres an den Code ran kommt. Hierfür könnt ihr das folgende Code-Snippet in eure functions.php
schreiben und den Slug des auszuschließenden Inhaltstypen verändern.
function kb_exclude_from_search($post_type){
global $wp_post_types;
$wp_post_types['page']->exclude_from_search = true;
add_post_type_support( 'page', 'page-attributes' );
}
add_action('registered_post_type', 'kb_exclude_from_search', 10, 2 );
Inhaltstypen in der Suche priorisieren
Um die einzelnen Inhaltstypen in der Suche zu priorisieren, schreibt folgenden Code in eure functions.php
und tragt alle eure Inhaltstypen vom Wichtigsten zum am wenig Wichtigsten nach dem Beispiel ein.
WICHTIG: Alle Inhaltstypen die nicht von der Suche ausgeschlossen sind müssen hier berücksichtigt werden, da die Suche sonst Fehler erzeugt!
function kb_order_post_types($a, $b) {
$order = [ 'product' => 0, 'post' => 1, 'page' => 2 ];
return $order[$a] - $order[$b];
}
Filter-Navigation erstellen und integrieren
Die Ausgabe der Suche wird in WordPress über die search.php gesteuert. Den folgenden Code müsst ihr nun in diese Datei zwischen dem Header (get_header()
) und dem Footer (get_footer()
) integrieren.
Kurz zusammengefasst, sagen wir dem System damit folgendes:
- Hole alle »Post Types« die nicht aus der Suche ausgeschlossen wurden
- Erstelle den globalen Search-Query für alle Suchergebnisse
- Prüfe ob der Parameter
search_type
gesetzt ist und vergebe die »Post Types« danach - Gehe die Suchergebnisse durch und zähle die Anzahl der einzelnen Inhalte in den »Post Types«
- Ordne die Post Types (mit unserer zuvor in der
functions.php
integrierten Priorisierung) - Gib einen Hinweistext aus, wieviele Ergebnisse insgesamt gefunden wurden
- Baue die Filter-Navigation (inkl. Anzahl der Ergebnisse pro Inhaltstyp)
// Hole alle »Post Types« die nicht aus der Suche ausgeschlossen wurden
$posttypes = get_post_types(array('exclude_from_search' => false));
// Erstelle den globalen Search-Query für alle Suchergebnisse
$global_search_args = array(
'post_type' => $posttypes,
'posts_per_page' => -1,
's' => get_search_query(),
'orderby' => 'relevance',
);
$global_search_query = new WP_Query($global_search_args);
// Prüfe ob der Parameter »search_type« gesetzt ist und vergebe die »Post Types« danach
if(isset($_GET['search_type'])) {
$posttype = $_GET['search_type'];
} else {
$posttype = $posttypes;
}
// Gehe die Suchergebnisse durch und zähle die Anzahl der einzelnen Inhalte in den »Post Types«
$posttype_arr = array();
$post_arr = array();
foreach($global_search_query->posts as $post) {
$posttype_arr[] = $post->post_type;
$post_arr[] = $post->ID;
}
$posttypes_in_search = array_count_values($posttype_arr);
// Ordne die Post Types
uksort($posttypes_in_search, 'kb_order_post_types');
// Gib einen Hinweistext aus, wieviele Ergebnisse insgesamt gefunden wurden
echo '<p>'.sprintf(_nx('Your search for „%1$s“ returned %2$s result.','Your search for „%1$s“ returned %2$s results.', $global_search_query->found_posts, 'Search result count','kb-theme'),get_search_query(),number_format_i18n( $global_search_query->found_posts )). '</p>';
// Baue die Filter-Navigation
if($posttypes_in_search) { ?>
<ul>
<?php foreach($posttypes_in_search as $posttype => $count) { ?>
<li class="<?php if(isset($_GET['search_type']) && $_GET['search_type'] == $posttype) { echo ' current'; } ?>">
<a href="<?php echo esc_url( home_url()).'?s='.urlencode(get_search_query()).'&search_type='.$posttype; ?>">
<?php echo get_post_type_object($posttype)->label; ?>
<span>(<?php echo $count; ?>)</span>
</a>
</li>
<?php } ?>
</ul>
<?php }
Gefilterte Suchergebnisse ausgeben
Zwischen dem Code der Filter-Navigation und dem Footer (get_footer()
) in der search.php
muss nun der Code für die Ausgabe der Suchergebnisse integriert werden.
Die Suchergebnisse erhalten wir durch Hilfe eines WP_Query dem wir Argumente übergeben. Einige dieser Argumente übernehmen wir aus dem Code für die Filter-Navigation. Als Ausgabe benutzen wir die get_template_part
Funktion. Diese Funktion müsst ihr je nach eurem verwendeten Theme anpassen, um die gewünschte Ausgabe zu erhalten.
Über paginate_links
haben wir eine Pagination integriert, die greift, wenn es mehr Suchergebnisse gibt, als auf einer Seite angezeigt werden sollen. Die Einstellung der Anzahl könnt ihr im Backend unter »Einstellungen → Lesen → Blogseiten zeigen maximal« finden.
// Erstelle den Search-Query
$count = get_option('posts_per_page', 12);
$paged = get_query_var('paged') ? get_query_var('paged') : 1;
$offset = ($paged - 1) * $count;
$posttypes = isset($_GET['search_type']) ? $_GET['search_type'] : $posttypes;
$search_args = array(
'post_type' => $posttypes,
'posts_per_page' => $count,
'post__in' => $post_arr,
'orderby' => 'post__in',
'paged' => $paged,
'offset' => $offset,
);
$search_query = new WP_Query( $search_args );
// Ausgabe der Suchergebnisse inkl. Pagination
if($search_query->have_posts() && !empty($post_arr)) {
echo '<ul>';
while ( $search_query->have_posts() ) { $search_query->the_post();
get_template_part('template-parts/teaser',get_post_type());
}
echo '</ul>';
wp_reset_postdata();
if ($search_query->max_num_pages > 1) {
echo '<div class="pagination">';
echo paginate_links( array(
'format' => 'page/%#%',
'end_size' => '0',
'mid_size' => '1',
'prev_text' => '«',
'next_text' => '»',
'current' => max( 1, get_query_var('paged') ),
'total' => $search_query->max_num_pages,
));
echo '</div>';
}
} else {
get_template_part('template-parts/content','none');
}
Filter-Auswahl nach Priorität automatisch festlegen
Zum Schluss müsst ihr noch den folgenden Code in eure functions.php
schreiben. Dieser bewirkt, dass ihr auch bei der ersten Verwendung der Suche auf den am höchsten priorisierten Inhaltstypen eurer Suche geleitet werdet.
Hierbei übergeben wir den $_GET
-Parameter search_type
und leiten mit Hilfe des template_redirect
Hooks die Standard-Suchergebnis-Seite um.
function kb_redirect_searchresults() {
// Hole alle »Post Types« die nicht von der Suche ausgeschlossen wurden
$posttypes = get_post_types(array('exclude_from_search' => false));
if (is_search() && !is_admin() && !isset($_GET['search_type'])) {
// Erstelle den globalen Search-Query für alle Suchergebnisse
$global_search_args = array(
'post_type' => $posttypes,
'posts_per_page' => -1,
's' => get_search_query(),
'orderby' => 'relevance',
);
$global_search_query = new WP_Query($global_search_args);
// Gehe die Suchergebnisse durch und zähle die Anzahl der einzelnen Posts in den »Post Types«
$posttype_arr = array();
foreach ( $global_search_query->posts as $post ) {
$posttype_arr[] = $post->post_type;
}
$posttypes_in_search = array_count_values($posttype_arr);
// Ordne die Post Types
uksort($posttypes_in_search, "kb_order_post_types");
// Schreibe den Parameter des am höchsten prirosierten »Post Types« mit Werten in die URL
if($posttypes_in_search) {
reset($posttypes_in_search);
$current = key($posttypes_in_search);
wp_redirect( esc_url( home_url()).'?s='.urlencode(get_search_query()).'&search_type='.$current );
exit;
}
}
}
add_action('template_redirect', 'kb_redirect_searchresults');
Ich sage nur: RESPEKT!
Toll ausgeführt und detailliert beschrieben – und genau das, was ich gesucht habe.
1000 Dank!
Muss das nicht exclude_from_search statt exclude_from_page heißen?
Hallo Michael,
da hast du natürlich recht. Wir haben es im Artikel korrigiert.
Viele Grüße
Robert