Tag Archives: WooCommerce

Nach dem vollen Namen suchen in WordPress geht nicht! Doch! Ooooh!

Wieder ein Problem, von dem man gar nicht denkt, daß es eins ist, bis man sich mal intensiver damit beschäftigt:

Kundin will die Benutzersuche erweitert haben. Standardmäßig kann man nur nach eMail-Adresse, Benutzernamen und WebSite-URL suchen, aber nicht nach Vorname, Nachname, Ort, PLZ oder Vor- + Nachnamen. Wieso das denn?

Das liegt vermutlich an der Struktur, wie die User in der Datenbank gespeichert sind. Die stehen in 2 Tabellen: wp_users und wp_usermeta.

In der wp_users steht nicht viel drin, aber wir haben die Spalten user_nicename, user_email und user_url. Das sind unsere Suchmöglichkeiten.
Die ganzen anderen Dinge stehen in der anderen Tabelle, der wp_usermeta, und die ist mit der wp_users über die ID verbunden:

 wp_posts.ID = wp_postmeta.user_id

Und hier haben wir jetzt plötzlich die interessanten Sachen: billing_first_name, billing_last_name und billing_city.

Also brauchen wir eine Suchfunktion danach. Ich hab bissl rumgegoogelt und das hier gefunden:

add_action( ‚pre_user_query‘, function( $uqi ) {
global $wpdb;
$search = “;
if ( isset( $uqi->query_vars[’search‘] ) )
$search = trim( $uqi->query_vars[’search‘] );if ( $search ) {
$search = trim($search, ‚*‘);
$the_search = ‚%‘.$search.’%‘;$search_meta = $wpdb->prepare(“
ID IN ( SELECT user_id FROM {$wpdb->usermeta}
WHERE ( ( meta_key=’first_name‘ OR meta_key=’last_name‘ )
AND {$wpdb->usermeta}.meta_value LIKE ‚%s‘ )
)“, $the_search);$uqi->query_where = str_replace(
‚WHERE 1=1 AND (‚,
„WHERE 1=1 AND (“ . $search_meta . “ OR „,
$uqi->query_where );
}
});

Aha aha!

EIgentlich dachte ich, man müßte eine Art SELECT user_id from wp_usermeta WHERE meta_key LIKE ‚billing_last_name‘ AND meta_value LIKE ‚%Suchbegriff%‘ machen, und dann die gefundene(n) User-ID(s) returnen oder sonstwie übergeben.

Aber der Autor des Snippets macht das anders: Er erweitert die Query erweitern, bevor sie ausgeführt wird, mit pre_user_query, und schreibt sich seine eigene WHERE-Bedingung, mit der er nachher die originale ($uqi->query_where) ersetzt. Toll. Ich kapiere seine syntaktischen Merkwürdigkeiten zwar nicht ganz, aber ich mach das jetzt auch so…und dann erweitere ich die eine Zeile noch mit der Stadt:

WHERE ( ( meta_key=’first_name‘ OR meta_key=’last_name‘ OR meta_key=’billing_city‘ )

Funktioniert.

Ich kann nach Heinz Becker in Bexbach suchen. ‚Heinz‘ findet alle Heinze, ‚Becker‘ alle Beckers, ‚Bexbach‘ alle, die in Bexbach wohnen. Oder auch die Bexbach heißen.

Äh…Moment…’Heinz Becker‘ findet gar nix. Nochmal die Query ansehen. Ja klar. Grmpf.
Die würde nur was finden, wenn Vorname, Nachname oder Stadt ‚Heinz Becker‘ heißen…tun sie aber nicht. Was nu?

Eigentlich müßte man 2 Abfragen machen, alle Heinze bei Vornamen, alle Beckers bei Nachnamen, und dann die User-ID ausgeben, die in beiden Abfragen enthalten ist.
Zuerst Vornamen namen suchen, ergibt ein Array der User-IDs aller Heinze. Danach dasselbe mit den Nachnamen, ergibt alle Beckers. Jetzt habe ich 2 Arrays.

Mit der schönen Funktion array_intersect kann ich rausfinden, ob es Elemente gibt, die in beiden Arrays vorhanden sind. Also da wo Vorname=Heinz und Nachname=Becker die gleiche user_id ergeben.

Klappt 🙂

Jetzt außendrum noch eine Abfrage, ob der Suchbegriff ein Leerzeichen enthält, damit eine einfache Suche weiterhin funktioniert.

Also so:

if (stristr($search, “ „)) {$search_exp = explode(“ „, $search);

// 1. Query: Vorname
$query1 = „SELECT * FROM wp_usermeta
WHERE meta_key = ‚first_name‘
AND meta_value LIKE ‚%“.$search_exp[0].“%'“;
$results1 = $wpdb->get_results($query1);
$vorname_ids = array();
foreach ($results1 as $key1 => $value1) {
$vorname_ids[] = $value1->user_id;
}

// 2. Query: Nachname
$query2 = „SELECT * FROM wp_usermeta
WHERE meta_key = ‚last_name‘
AND meta_value LIKE ‚%“.$search_exp[1].“%'“;
$results2 = $wpdb->get_results($query2);
$nachname_ids = array();
foreach ($results2 as $key2 => $value2) {
$nachname_ids[] = $value2->user_id;
}

$fullname_ids = array_intersect($vorname_ids, $nachname_ids);
$fullname_ids = implode(„,“, $fullname_ids);

$search_meta = $wpdb->prepare(“
ID IN (‚%s‘)“, $fullname_ids);

$uqi->query_where = str_replace(
‚WHERE 1=1 AND (‚,
„WHERE 1=1 AND (“ . $search_meta . “ OR „,
$uqi->query_where );
}

Klappt.

Vollständiger Code:

add_action( ‚pre_user_query‘, function( $uqi ) {
global $wpdb;

$search = “;
if ( isset( $uqi->query_vars[’search‘] ) )
$search = trim( $uqi->query_vars[’search‘] );

if ( $search ) {
$search = trim($search, ‚*‘);

if (stristr($search, “ „)) {

$search_exp = explode(“ „, $search);

// 1. Query: Vorname
$query1 = „SELECT * FROM wp_usermeta
WHERE meta_key = ‚first_name‘
AND meta_value LIKE ‚%“.$search_exp[0].“%'“;
$results1 = $wpdb->get_results($query1);
$vorname_ids = array();
foreach ($results1 as $key1 => $value1) {
$vorname_ids[] = $value1->user_id;
}

// 2. Query: Nachname
$query2 = „SELECT * FROM wp_usermeta
WHERE meta_key = ‚last_name‘
AND meta_value LIKE ‚%“.$search_exp[1].“%'“;
$results2 = $wpdb->get_results($query2);
$nachname_ids = array();
foreach ($results2 as $key2 => $value2) {
$nachname_ids[] = $value2->user_id;
}

$fullname_ids = array_intersect($vorname_ids, $nachname_ids);
$fullname_ids = implode(„,“, $fullname_ids);

$search_meta = $wpdb->prepare(“
ID IN (‚%s‘)“, $fullname_ids);

$uqi->query_where = str_replace(
‚WHERE 1=1 AND (‚,
„WHERE 1=1 AND (“ . $search_meta . “ OR „,
$uqi->query_where );
}
else {
$the_search = ‚%‘.$search.’%‘;

$search_meta = $wpdb->prepare(“
ID IN ( SELECT user_id FROM {$wpdb->usermeta}
WHERE ( ( meta_key=’first_name‘ OR meta_key=’last_name‘ OR meta_key=’billing_city‘ )
AND {$wpdb->usermeta}.meta_value LIKE ‚%s‘ )
)“, $the_search);

$uqi->query_where = str_replace(
‚WHERE 1=1 AND (‚,
„WHERE 1=1 AND (“ . $search_meta . “ OR „,
$uqi->query_where );
}
}
});

Wieder ein Bewerbungstest

Ich suche ja immer wieder nach neuen Jobs und Projekten für WordPress und WooCommerce.
Neulich gab es eine vielversprechende Resonanz. Ich müßte aber einen Test machen. („dauert nicht lange“)

Ich hatte nicht viel zu tun und hab den Test gemacht.  7 Aufgaben, und dann noch 2 Stolpersteine, bis man erst mal drankommt.

Habe alles gelöst. Größtenteils mit Code-Snippets in PHP und jQuery, z.T. gefunden, z.T. selbst programmiert. Ich wollte auf keinen Fall Plugins installieren, wo ein 4- oder 6-Zeiler auch genügen würde.

Bei der Vorstellung meiner Lösungen wurde ich dann gefragt, warum ich denn keine Plugins verwendet habe. Ich hab dann gesagt „aus Performancegründen natürlich“ und erwähnt, daß ich beim Geschwindigkeitsoptimieren vieler Seiten und Shops immer wieder auf Plugins stoße, die die Seite verlangsamen, FrontEnd und BackEnd.

Die Aufgabenstellung enthielt keine Anweisung, Plugins zu verwenden oder nicht zu verwenden, es wurde mir mehrfach versichert, daß der Lösungsweg nicht wichtig ist, solange es funktioniert. Trotzdem gab es eine Absage. Der Grund dafür wurde mir nicht mitgeteilt. Ich nehme an es liegt an meiner Philosophie der Plugin-freien Lösungen.

Letztendlich sehe ich das aber positiv…die Leute bauen ihre WordPress-Seiten und ihre WooCommerce-Shops komplett mit Plugins zu, und irgendwann gibt das Krieg, spätestens bei 50-70 Plugins, aber oft auch schon früher.

Die kommen dann zu mir und möchten, daß ich die Seite schneller mache 😀