Dichiarazione di non responsabilità importante: il modo corretto per farlo NON è modificare la struttura della tabella, ma usare wp_usermeta. Quindi non sarà necessario creare alcun SQL personalizzato per interrogare i tuoi post (anche se avrai comunque bisogno di alcuni SQL personalizzati per ottenere un elenco di tutti coloro che segnalano a un supervisore particolare, ad esempio nella sezione Amministratore). Tuttavia, poiché l'OP ha chiesto di scrivere un SQL personalizzato, ecco la migliore procedura corrente per iniettare un SQL personalizzato in una query WordPress esistente.
Se stai eseguendo join complessi, non puoi semplicemente utilizzare il filtro posts_where, poiché dovrai modificare il join, la selezione e, eventualmente, il gruppo o anche l'ordine per sezioni della query.
La soluzione migliore è utilizzare il filtro "posts_clauses". Questo è un filtro molto utile (che non dovrebbe essere abusato!) Che ti consente di aggiungere / modificare le varie porzioni di SQL generate automaticamente dalle molte molte righe di codice all'interno del core di WordPress. La firma del callback del filtro è:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
e si aspetta che tu ritorni $clauses
.
Le clausole
$clauses
è un array che contiene le seguenti chiavi; ogni chiave è una stringa SQL che verrà utilizzata direttamente nell'istruzione SQL finale inviata al database:
- dove
- raggruppare per
- aderire
- ordinato da
- distinto
- i campi
- limiti
Se stai aggiungendo una tabella al database (fallo solo se non riesci assolutamente a sfruttare post_meta, user_meta o tassonomie) probabilmente dovrai toccare più di una di queste clausole, ad esempio il fields
(il "SELEZIONA" parte dell'istruzione SQL), la join
(tutte le tabelle, tranne quella nella clausola "FROM") e forse la orderby
.
Modifica delle clausole
Il modo migliore per farlo è sottoporre la chiave pertinente $clauses
all'array ottenuto dal filtro:
$join = &$clauses['join'];
Ora, se modifichi $join
, in realtà modificherai direttamente in $clauses['join']
modo che le modifiche vengano apportate $clauses
quando lo restituisci.
Preservare le clausole originali
È probabile (no, seriamente, ascolta) che vorrai preservare l'SQL esistente che WordPress ha generato per te. In caso contrario, dovresti probabilmente guardare il posts_request
filtro, ovvero la query mySQL completa appena prima che venga inviata al database, quindi puoi bloccarlo totalmente con il tuo. Perché vorresti farlo? Probabilmente no.
Quindi, al fine di preservare l'SQL esistente nelle clausole, ricordati di aggiungere alle clausole, non di assegnarle (cioè: usa $join .= ' {NEW SQL STUFF}';
non $join = '{CLOBBER SQL STUFF}';
. Nota che poiché ogni elemento $clauses
dell'array è una stringa, se vuoi aggiungerlo, probabilmente vorrai inserire uno spazio prima di qualsiasi altro token di carattere, altrimenti creerai probabilmente un errore di sintassi SQL.
Puoi solo supporre che ci sarà sempre qualcosa in ciascuna delle clausole, quindi ricorda di iniziare ogni nuova stringa con uno spazio, come in: $join .= ' my_table
oppure, puoi sempre aggiungere una piccola riga che aggiunge uno spazio solo se è necessario:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
Questa è una cosa stilistica più di ogni altra cosa. Il bit importante da ricordare è: lasciare sempre uno spazio PRIMA della stringa se si aggiunge a una clausola che contiene già un codice SQL!
Mettendolo insieme
La prima regola dello sviluppo di WordPress è cercare di utilizzare quante più funzionalità di base possibile. Questo è il modo migliore per rendere il tuo lavoro a prova di futuro. Supponiamo che il core team decida che WordPress ora utilizzerà SQLite o Oracle o qualche altro linguaggio di database. Qualsiasi mySQL scritto a mano può diventare non valido e interrompere il tuo plugin o tema! Meglio consentire a WP di generare da solo il maggior numero possibile di SQL e aggiungere semplicemente i bit necessari.
Pertanto, il primo ordine del giorno è sfruttare la WP_Query
maggior quantità possibile di query di base. Il metodo esatto che utilizziamo per farlo dipende in gran parte da dove dovrebbe apparire questo elenco di post. Se si tratta di una sottosezione della pagina (non la query principale) che useresti get_posts()
; se è la query principale, suppongo che potresti usarla query_posts()
e farla finita, ma il modo corretto per farlo è intercettare la query principale prima che colpisca il database (e consumi i cicli del server), quindi usa il request
filtro.
Ok, quindi hai generato la tua query e sta per essere creato l'SQL. Bene, in effetti, è stato creato, ma non inviato al database. Utilizzando il posts_clauses
filtro, aggiungerai la tabella delle relazioni con i dipendenti nel mix. Chiamiamo questa tabella {$ wpdb-> prefisso}. 'user_relationship', ed è una tabella di intersezione. (A proposito, ti consiglio di generalizzare questa struttura di tabella e trasformarla in una tabella di intersezione appropriata con i seguenti campi: 'relationship_id', 'user_id', 'related_user_id', 'relationship_type'; questo è molto più flessibile e potente. .. ma sto divagando).
Se capisco cosa vuoi fare, vuoi passare l'ID di un leader e quindi vedere solo i post dei follower di quel leader. Spero di aver capito bene. Se non è giusto, dovrai prendere ciò che dico e adattarlo alle tue esigenze. Seguirò la struttura del tuo tavolo: abbiamo a leader_id
e a follower_id
. Quindi JOIN sarà {$wpdb->posts}.post_author
attivo come chiave esterna per "follower_id" nella tabella "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;
}