Penafian penting: cara yang tepat untuk melakukan ini BUKAN untuk mengubah struktur tabel Anda, tetapi untuk menggunakan wp_usermeta. Maka Anda tidak perlu membuat SQL khusus untuk menanyakan posting Anda (meskipun Anda masih membutuhkan SQL khusus untuk mendapatkan daftar semua orang yang melapor ke supervisor tertentu - di bagian Admin, misalnya). Namun, sejak OP bertanya tentang menulis SQL kustom, berikut ini praktik terbaik saat ini untuk menyuntikkan SQL kustom ke dalam Query WordPress yang ada.
Jika Anda melakukan gabungan yang rumit, Anda tidak bisa hanya menggunakan filter posts_where, karena Anda harus memodifikasi gabungan, pilih, dan mungkin grup berdasarkan atau pesan dengan bagian dari permintaan juga.
Taruhan terbaik Anda adalah dengan menggunakan filter 'posts_clauses'. Ini adalah filter yang sangat berguna (yang tidak boleh disalahgunakan!) Yang memungkinkan Anda untuk menambahkan / memodifikasi berbagai bagian dari SQL yang dihasilkan secara otomatis oleh banyak baris kode dalam inti WordPress. Tanda tangan panggilan balik filter adalah:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
dan mengharapkan Anda untuk kembali $clauses
.
Klausul
$clauses
adalah array yang berisi kunci-kunci berikut; setiap kunci adalah string SQL yang akan langsung digunakan dalam pernyataan SQL akhir yang dikirim ke database:
- dimana
- groupby
- ikut
- dipesan oleh
- berbeda
- bidang
- batas
Jika Anda menambahkan tabel ke database (hanya lakukan ini jika Anda benar-benar tidak dapat memanfaatkan post_meta, user_meta atau taksonomi) Anda mungkin perlu menyentuh lebih dari satu klausa ini, misalnya, the fields
("SELECT" bagian dari pernyataan SQL), join
(semua tabel Anda, selain yang ada di klausa "FROM" Anda), dan mungkin orderby
.
Mengubah Klausa
Cara terbaik untuk melakukan ini adalah dengan mensubreferensi kunci yang relevan dari $clauses
array yang Anda dapatkan dari filter:
$join = &$clauses['join'];
Sekarang, jika Anda memodifikasi $join
, Anda benar-benar akan langsung memodifikasi $clauses['join']
sehingga perubahan akan terjadi $clauses
ketika Anda mengembalikannya.
Melestarikan Klausa Asli
Kemungkinannya adalah (tidak, serius, dengarkan) Anda ingin mempertahankan SQL yang ada yang dihasilkan WordPress untuk Anda. Jika tidak, Anda mungkin harus melihat posts_request
filter sebagai gantinya - itu adalah permintaan mySQL lengkap sebelum dikirim ke database, sehingga Anda benar-benar dapat mengatasinya dengan Anda sendiri. Mengapa Anda ingin melakukan ini? Kamu mungkin tidak.
Jadi, untuk melestarikan SQL yang ada di klausa, ingatlah untuk menambahkan klausa, tidak menetapkan untuk mereka (yaitu: gunakan $join .= ' {NEW SQL STUFF}';
tidak $join = '{CLOBBER SQL STUFF}';
. Perhatikan bahwa karena setiap elemen dari $clauses
array adalah string, jika Anda ingin menambahkannya, Anda mungkin ingin memasukkan spasi sebelum token karakter lain, jika tidak, Anda mungkin akan membuat beberapa kesalahan sintaks SQL.
Anda bisa saja berasumsi akan selalu ada sesuatu di setiap klausa, dan jadi ingatlah untuk memulai setiap string baru dengan spasi, seperti pada:, $join .= ' my_table
atau, Anda selalu dapat menambahkan garis kecil yang hanya menambah ruang jika Anda perlu:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
Itu hal yang gaya lebih dari apa pun. Bit penting untuk diingat adalah: selalu meninggalkan ruang SEBELUM string Anda jika Anda menambahkan klausa yang sudah memiliki beberapa SQL di dalamnya!
Menyatukannya
Aturan pertama pengembangan WordPress adalah mencoba menggunakan sebanyak mungkin fungsionalitas inti. Ini adalah cara terbaik untuk membuktikan pekerjaan Anda di masa depan. Misalkan tim inti memutuskan bahwa WordPress sekarang akan menggunakan SQLite atau Oracle atau bahasa database lainnya. MySQL yang ditulis tangan dapat menjadi tidak valid dan merusak plugin atau tema Anda! Lebih baik membiarkan WP menghasilkan SQL sebanyak mungkin sendiri, dan tambahkan saja bit yang Anda butuhkan.
Jadi urutan pertama bisnis adalah meningkatkan WP_Query
untuk menghasilkan sebanyak mungkin permintaan dasar Anda. Metode tepat yang kita gunakan untuk melakukan ini sangat tergantung pada di mana daftar posting ini seharusnya muncul. Jika itu adalah sub-bagian halaman (bukan permintaan utama Anda) yang akan Anda gunakan get_posts()
; jika itu permintaan utama, saya kira Anda bisa menggunakan query_posts()
dan menyelesaikannya, tetapi cara yang tepat untuk melakukannya adalah dengan mencegat permintaan utama sebelum menyentuh database (dan menggunakan siklus server) jadi gunakan request
filter.
Oke, jadi Anda telah membuat kueri dan SQL akan segera dibuat. Sebenarnya, itu telah dibuat, tidak dikirim ke basis data. Dengan menggunakan posts_clauses
filter, Anda akan menambahkan tabel hubungan karyawan Anda ke dalam campuran. Sebut saja tabel ini {$ wpdb-> awalan}. 'user_relationship', dan ini adalah tabel persimpangan. (Omong-omong, saya sarankan Anda membuat generik struktur tabel ini dan mengubahnya menjadi tabel persimpangan yang tepat dengan bidang-bidang berikut: 'relationship_id', 'user_id', 'related_user_id', 'relationship_type'; ini jauh lebih fleksibel dan kuat. .. tapi saya ngelantur).
Jika saya mengerti apa yang ingin Anda lakukan, Anda ingin memberikan ID Pemimpin dan kemudian hanya melihat posting oleh Pengikut Pemimpin itu. Saya harap saya benar. Jika itu tidak benar, Anda harus menerima apa yang saya katakan dan menyesuaikannya dengan kebutuhan Anda. Saya akan tetap dengan struktur meja Anda: kami memiliki a leader_id
dan a follower_id
. Jadi GABUNG akan diaktifkan {$wpdb->posts}.post_author
sebagai kunci asing ke 'follower_id' di tabel 'user_relationship' Anda.
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;
}