Wichtiger Hinweis: Der richtige Weg, dies zu tun, besteht NICHT darin, Ihre Tabellenstruktur zu ändern, sondern wp_usermeta zu verwenden. Dann müssen Sie kein benutzerdefiniertes SQL erstellen, um Ihre Posts abzufragen (obwohl Sie immer noch benutzerdefiniertes SQL benötigen, um eine Liste aller Benutzer zu erhalten, die einem bestimmten Supervisor Bericht erstatten - beispielsweise im Abschnitt "Admin"). Da das OP jedoch nach dem Schreiben von benutzerdefiniertem SQL gefragt hat, wird im Folgenden die derzeit empfohlene Vorgehensweise zum Injizieren von benutzerdefiniertem SQL in eine vorhandene WordPress-Abfrage beschrieben.
Wenn Sie komplexe Verknüpfungen ausführen, können Sie nicht einfach den Filter posts_where verwenden, da Sie die Verknüpfung, die Auswahl und möglicherweise auch die Gruppierung nach oder die Reihenfolge nach Abschnitten der Abfrage ändern müssen.
Verwenden Sie am besten den Filter "posts_clauses". Dies ist ein äußerst nützlicher Filter (der nicht missbraucht werden sollte!), Mit dem Sie die verschiedenen Teile der SQL-Anweisung anhängen / ändern können, die von den vielen Codezeilen in WordPress Core automatisch generiert werden. Die Filterrückrufsignatur lautet:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
und erwartet, dass Sie zurückkehren $clauses
.
Die Klauseln
$clauses
ist ein Array, das die folgenden Schlüssel enthält; Jeder Schlüssel ist eine SQL-Zeichenfolge, die direkt in der endgültigen SQL-Anweisung verwendet wird, die an die Datenbank gesendet wird:
- woher
- gruppiere nach
- Beitreten
- Sortieren nach
- deutlich
- Felder
- Grenzen
Wenn Sie eine Tabelle in der Datenbank sind hinzugefügt (dies nur tun , wenn Sie absolut nicht Hebel post_meta, user_meta oder Taxonomien) Sie wahrscheinlich mehr als eine dieser Klauseln zum Beispiel die brauchen, zu berühren fields
(die „SELECT“ Teil der SQL - Anweisung), die join
(alle Ihre Tabellen, außer der in Ihrer "FROM" - Klausel) und möglicherweise die orderby
.
Änderung der Klauseln
Am besten referenzieren Sie dazu den relevanten Schlüssel aus dem $clauses
Array, das Sie vom Filter erhalten haben:
$join = &$clauses['join'];
Wenn Sie jetzt $join
Änderungen $clauses['join']
vornehmen , werden Sie diese direkt ändern , sodass die Änderungen $clauses
bei der Rückgabe übernommen werden.
Erhalt der ursprünglichen Klauseln
Wahrscheinlich möchten Sie (im Ernst, hören Sie zu) das vorhandene SQL, das WordPress für Sie generiert hat, beibehalten. Wenn nicht, sollten Sie sich posts_request
stattdessen wahrscheinlich den Filter ansehen - das ist die vollständige mySQL-Abfrage, kurz bevor sie an die Datenbank gesendet wird. Warum willst du das tun? Sie wahrscheinlich nicht.
Um die vorhandene SQL in den Klauseln beizubehalten, müssen Sie daran denken, an die Klauseln anzuhängen und sie nicht zuzuweisen (dh: Verwenden Sie $join .= ' {NEW SQL STUFF}';
nicht $join = '{CLOBBER SQL STUFF}';
. Beachten Sie, dass jedes Element des $clauses
Arrays eine Zeichenfolge ist, wenn Sie daran anhängen möchten. Sie werden wahrscheinlich ein Leerzeichen vor anderen Zeichen-Token einfügen wollen, andernfalls werden Sie wahrscheinlich einen SQL-Syntaxfehler erzeugen.
Sie können einfach davon ausgehen, dass in jeder Klausel immer etwas enthalten ist, und denken Sie daher daran, jede neue Zeichenfolge mit einem Leerzeichen wie in: $join .= ' my_table
zu beginnen.
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
Das ist mehr als alles andere eine stilistische Sache. Das Wichtigste, an das Sie sich erinnern sollten, ist: Lassen Sie immer ein Leerzeichen VOR Ihrer Zeichenfolge, wenn Sie an eine Klausel anhängen, in der bereits SQL enthalten ist!
Etwas zusammensetzen
Die erste Regel bei der Entwicklung von WordPress ist, so viele Kernfunktionen wie möglich zu verwenden. Dies ist der beste Weg, um Ihre Arbeit zukunftssicher zu machen. Angenommen, das Kernteam entscheidet, dass WordPress jetzt SQLite oder Oracle oder eine andere Datenbanksprache verwendet. Jedes handgeschriebene mySQL kann ungültig werden und Ihr Plugin oder Theme beschädigen! Es ist besser, WP so viel SQL wie möglich selbst generieren zu lassen und nur die benötigten Bits hinzuzufügen.
Die erste Geschäftsaufgabe besteht also WP_Query
darin, so viel wie möglich von Ihrer Basisabfrage zu generieren. Die genaue Methode, mit der wir dies tun, hängt weitgehend davon ab, wo diese Liste der Beiträge erscheinen soll. Wenn es sich um einen Unterabschnitt der Seite handelt (nicht um Ihre Hauptabfrage), würden Sie verwenden get_posts()
. Wenn es sich um die Hauptabfrage handelt, können Sie sie vermutlich verwenden query_posts()
und damit fertig werden. Die richtige Methode besteht jedoch darin, die Hauptabfrage abzufangen, bevor sie die Datenbank erreicht (und Serverzyklen beansprucht). Verwenden Sie daher den request
Filter.
Okay, Sie haben Ihre Abfrage generiert und die SQL wird erstellt. Tatsächlich wurde es erstellt, aber nicht an die Datenbank gesendet. Mit dem posts_clauses
Filter fügen Sie Ihre Mitarbeiterbeziehungstabelle in den Mix ein. Nennen wir diese Tabelle {$ wpdb-> Präfix}. 'user_relationship' und es ist eine Kreuzungstabelle. (Übrigens empfehle ich, diese Tabellenstruktur zu generieren und in eine richtige Schnittstellentabelle mit den folgenden Feldern umzuwandeln: 'relationship_id', 'user_id', 'related_user_id', 'relationship_type'; dies ist viel flexibler und leistungsfähiger. .. Aber ich schweife ab).
Wenn ich verstehe, was Sie tun möchten, möchten Sie die ID eines Anführers übergeben und dann nur die Beiträge der Anhänger dieses Anführers anzeigen. Ich hoffe, ich habe das richtig verstanden. Wenn es nicht stimmt, müssen Sie das, was ich sage, nehmen und an Ihre Bedürfnisse anpassen. Ich bleibe bei deiner Tischstruktur: Wir haben ein leader_id
und ein follower_id
. Daher ist JOIN {$wpdb->posts}.post_author
als Fremdschlüssel für die 'follower_id' in Ihrer 'user_relationship'-Tabelle aktiviert.
add_filter( 'posts_clauses', 'filter_by_leader_id', 10, 2 ); // we need the 2 because we want to get all the arguments
function filter_by_leader_id( $clauses, $query_object ){
// I don't know how you intend to pass the leader_id, so let's just assume it's a global
global $leader_id;
// In this example I only want to affect a query on the home page.
// This is where the $query_object is used, to help us avoid affecting
// ALL queries (since ALL queries pass through this filter)
if ( $query_object->is_home() ){
// Now, let's add your table into the SQL
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' '; // add a space only if we have to (for bonus marks!)
$join .= "JOIN {$wpdb->prefix}employee_relationship EMP_R ON EMP_R.follower_id = {$wpdb->posts}.author_id";
// And make sure we add it to our selection criteria
$where = &$clauses['where'];
// Regardless, you always start with AND, because there's always a '1=1' statement as the first statement of the WHERE clause that's added in by WP/
// Just don't forget the leading space!
$where .= " AND EMP_R.leader_id={$leader_id}"; // assuming $leader_id is always (int)
// And I assume you'll want the posts "grouped" by user id, so let's modify the groupby clause
$groupby = &$clauses['groupby'];
// We need to prepend, so...
if (! empty( $groupby ) ) $groupby = ' ' . $groupby; // For the show-offs
$groupby = "{$wpdb->posts}.post_author" . $groupby;
}
// Regardless, we need to return our clauses...
return $clauses;
}