Benutzerdefinierte Felder gehören zu den leistungsstarken Funktionen in WordPress. Sie sind besonders nützlich, wenn man WordPress über die Verwendung von benutzerdefinierten Post-Arten erweitert möchte. Bei der Entwicklung von WordPress-Themes für Kunden erstelle ich immer wieder eigene Post-Typen für Produkte, Portfolios oder Galerien.

Benutzerdefinierte Felder sind äußerst praktisch, wenn es darum geht, Produktdetails wie Artikelnummern oder Preise hinzuzufügen. Leider ist es nicht möglich, WordPress-Inhalte nach benutzerdefinierten Feldern zu durchsuchen.

Man kanndieses Manko jedoch beheben und die WordPress-Suchabfrage so anpassen, dass sie auch benutzerdefinierte Felder berücksichtigt.

In der Postmeta-Tabelle werden alle benutzerdefinierten Felddaten in der Datenbank gespeichert. Standardmäßig ist die WordPress-Suchfunktion so eingestellt, dass nur die “posts” -Tabelle durchsucht wird. Um die Daten der benutzerdefinierten Felder in die Suche einzubeziehen, müssen wir zunächst einen Link-Verbindung für die Tabellen ‘posts’ und ‘postmeta’ in der Datenbank durchführen.

/**
* Posts und Postmeta Tabellen verbinden
*
* http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join
*/
function cf_search_join( $join ) {
global $wpdb;

if ( is_search() ) {
$join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
}

return $join;
}
add_filter('posts_join', 'cf_search_join' );

Abfrageänderung

Als nächstes müssen wir die WordPress-Suchabfrage ändern, um die benutzerdefinierten Felder aufzunehmen.

/**
* Ändern der Suchanfrage mit posts_where
*
* http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
*/
function cf_search_where( $where ) {
global $pagenow, $wpdb;

if ( is_search() ) {
$where = preg_replace(
"/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
"(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );
}

return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

Duplikate verhindern

Schließlich müssen wir der SQL-Abfrage das Schlüsselwort DISTINCT hinzufügen, um die Rückgabe von Duplikaten zu verhindern.

/**
* Duplikate verhindern
*
* http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
*/
function cf_search_distinct( $where ) {
global $wpdb;

if ( is_search() ) {
return "DISTINCT";
}

return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );

Zusammenfügen

Fügen Sie den folgenden Codeschnipsel der functions.php hinzu, damit WordPress auch benutzerdefinierte Feldern durchsuchen kann. Dieser Code wird nicht nur die Suche im Frontend modifizieren, sondern Sie können auch im Dashboard benutzerdefinierte Felder durchsuchen.

/**
 * Extend WordPress search to include custom fields
 *
 * https://adambalee.com
 */

/**
 * Join posts and postmeta tables
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join
 */
function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {    
        $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }

    return $join;
}
add_filter('posts_join', 'cf_search_join' );

/**
 * Modify the search query with posts_where
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where
 */
function cf_search_where( $where ) {
    global $pagenow, $wpdb;

    if ( is_search() ) {
        $where = preg_replace(
            "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
            "(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );
    }

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

/**
 * Prevent duplicates
 *
 * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct
 */
function cf_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );