Ważna informacja: właściwym sposobem na to NIE jest modyfikowanie struktury tabeli, ale użycie wp_usermeta. Wówczas nie będziesz musiał tworzyć niestandardowego kodu SQL do wysyłania zapytań do swoich postów (choć nadal potrzebujesz niestandardowego kodu SQL, aby uzyskać listę wszystkich, którzy zgłaszają się do określonego przełożonego - na przykład w sekcji Administrator). Ponieważ jednak OP poprosił o napisanie niestandardowego SQL, oto najlepsza praktyka wprowadzania niestandardowego SQL do istniejącego zapytania WordPress.
Jeśli wykonujesz złożone sprzężenia, nie możesz po prostu użyć filtra posts_where, ponieważ musisz zmodyfikować sprzężenie, zaznaczenie i ewentualnie grupę według lub uporządkować według sekcji zapytania.
Najlepiej jest użyć filtra „posts_clauses”. Jest to bardzo przydatny filtr (który nie powinien być nadużywany!), Który pozwala dodawać / modyfikować różne części SQL generowane automatycznie przez wiele wierszy kodu w rdzeniu WordPress. Sygnatura oddzwaniania filtra to:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
i oczekuje na powrót $clauses
.
Klauzule
$clauses
jest tablicą zawierającą następujące klucze; każdy klucz jest ciągiem SQL, który zostanie bezpośrednio użyty w końcowej instrukcji SQL wysłanej do bazy danych:
- gdzie
- Grupuj według
- Przystąpić
- Zamów przez
- odrębny
- pola
- limity
Jeśli dodajesz tabelę do bazy danych (rób to tylko wtedy, gdy absolutnie nie możesz wykorzystać post_meta, user_meta lub taksonomii) prawdopodobnie będziesz musiał dotknąć więcej niż jednej z tych klauzul, na przykład fields
(„WYBIERZ” część instrukcji SQL), join
(wszystkie tabele, inne niż w klauzuli „FROM”) i być może orderby
.
Modyfikowanie klauzul
Najlepszym sposobem na to jest odjęcie odpowiedniego klucza z $clauses
tablicy uzyskanej z filtra:
$join = &$clauses['join'];
Teraz, jeśli zmodyfikujesz $join
, będziesz modyfikować bezpośrednio, $clauses['join']
więc zmiany zostaną wprowadzone $clauses
po jego zwróceniu.
Zachowanie oryginalnych klauzul
Możliwe, że (nie, poważnie, słuchaj) będziesz chciał zachować istniejący SQL wygenerowany dla Ciebie przez WordPress. Jeśli nie, prawdopodobnie powinieneś posts_request
zamiast tego spojrzeć na filtr - jest to kompletne zapytanie mySQL tuż przed wysłaniem go do bazy danych, abyś mógł całkowicie zablokować go własnym. Dlaczego chcesz to zrobić? Prawdopodobnie nie.
Aby zachować istniejący kod SQL w klauzulach, pamiętaj o dołączeniu do klauzul, a nie przypisaniu do nich (tj.: $join .= ' {NEW SQL STUFF}';
Nie używaj $join = '{CLOBBER SQL STUFF}';
. Zauważ, że ponieważ każdy element $clauses
tablicy jest łańcuchem, jeśli chcesz do niego dołączyć, prawdopodobnie będziesz chciał wstawić spację przed innymi tokenami znaków, w przeciwnym razie prawdopodobnie utworzysz jakiś błąd składni SQL.
Możesz po prostu założyć, że zawsze będzie coś w każdej z klauzul, więc pamiętaj, aby rozpocząć każdy nowy ciąg spacją, jak w:, $join .= ' my_table
lub zawsze możesz dodać małą linię, która dodaje spację tylko wtedy, gdy potrzebujesz:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
To stylistyczna rzecz bardziej niż cokolwiek innego. Ważną rzeczą do zapamiętania jest: zawsze zostawiaj spację PRZED łańcuchem, jeśli dołączasz do klauzuli, która zawiera już trochę SQL!
Składając to razem
Pierwszą zasadą rozwoju WordPressa jest próba użycia jak największej liczby podstawowych funkcji. To najlepszy sposób, aby w przyszłości sprawdzić swoją pracę. Załóżmy, że główny zespół zdecyduje, że WordPress będzie teraz używać SQLite, Oracle lub innego języka baz danych. Każdy ręcznie napisany mySQL może stać się nieważny i uszkodzić wtyczkę lub motyw! Lepiej pozwolić WP generować tak dużo SQL, jak to możliwe, i po prostu dodać potrzebne bity.
Tak więc pierwsze zamówienie firmy wykorzystuje WP_Query
do wygenerowania jak największej liczby zapytań podstawowych. Dokładna metoda, której używamy, zależy w dużej mierze od tego, gdzie ta lista postów ma się pojawić. Jeśli jest to podsekcja strony (nie twoje główne zapytanie), skorzystasz get_posts()
; jeśli jest to główne zapytanie, myślę, że można go użyć query_posts()
i gotowe, ale właściwym sposobem na to jest przechwycenie głównego zapytania, zanim trafi ono do bazy danych (i zużyje cykle serwera), więc użyj request
filtru.
OK, więc wygenerowałeś zapytanie i SQL zostanie wkrótce stworzony. Cóż, w rzeczywistości został stworzony, po prostu nie wysłany do bazy danych. Korzystając z posts_clauses
filtra, dodasz tabelę relacji pracowniczych do miksu. Nazwijmy tę tabelę {$ wpdb-> prefix}. „user_relationship” i jest to tabela skrzyżowań. (Nawiasem mówiąc, zalecam uogólnienie tej struktury tabeli i przekształcenie jej w odpowiednią tabelę przecięcia z następującymi polami: „id_użytkownika”, „id_użytkownika”, „id_użytkownika_użytkownika”, „typ_użytkownika”; jest to o wiele bardziej elastyczne i wydajne. .. ale dygresję).
Jeśli rozumiem, co chcesz zrobić, chcesz przekazać identyfikator lidera, a następnie zobaczyć tylko posty obserwujących tego lidera. Mam nadzieję, że dobrze to zrozumiałem. Jeśli to nie w porządku, musisz wziąć to, co mówię i dostosować to do swoich potrzeb. Pozostanę przy twojej strukturze stołu: mamy a leader_id
i a follower_id
. Tak więc JOIN będzie włączony {$wpdb->posts}.post_author
jako klucz obcy do „follower_id” w tabeli „user_relationship”.
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;
}