Saya sudah berhari-hari membahas masalah ini sekarang. Awalnya itu adalah, bagaimana cara menyimpan data pengikut pengguna dalam database, yang saya dapatkan beberapa rekomendasi bagus di sini di WordPress Answers. Setelah, mengikuti rekomendasi saya telah menambahkan tabel baru seperti ini:
id leader_id follower_id
1 2 4
2 3 10
3 2 10
Pada tabel di atas, baris pertama memiliki pengguna dengan ID 2 yang sedang diikuti oleh pengguna dengan ID 4. Di baris kedua, pengguna dengan ID 3 sedang diikuti oleh pengguna dengan ID 10. Logika yang sama berlaku untuk baris ketiga.
Sekarang, pada dasarnya saya ingin memperluas WP_Query sehingga saya dapat membatasi posting yang diambil dari, hanya oleh pemimpin pengguna. Jadi, dengan mempertimbangkan tabel di atas, jika saya harus memberikan ID pengguna 10 ke WP_Query hasilnya hanya akan berisi posting dengan ID pengguna 2 dan ID pengguna 3.
Saya telah mencari banyak berusaha untuk menemukan jawaban. Saya juga tidak melihat tutorial apa pun untuk membantu saya memahami cara memperluas kelas WP_Query. Saya telah melihat jawaban Mike Schinkel (memperluas WP_Query) untuk pertanyaan serupa, tetapi saya benar-benar tidak mengerti bagaimana menerapkannya pada kebutuhan saya. Akan lebih bagus jika seseorang bisa membantu saya dengan ini.
Tautan ke jawaban Mike seperti yang diminta: Tautan 1 , Tautan 2
WP_Query
adalah untuk mendapatkan posting, dan saya gagal memahami bagaimana ini terkait dengan posting.Jawaban:
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: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 mungkinorderby
.Mengubah Klausa
Cara terbaik untuk melakukan ini adalah dengan mensubreferensi kunci yang relevan dari
$clauses
array yang Anda dapatkan dari filter: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: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 gunakanget_posts()
; jika itu permintaan utama, saya kira Anda bisa menggunakanquery_posts()
dan menyelesaikannya, tetapi cara yang tepat untuk melakukannya adalah dengan mencegat permintaan utama sebelum menyentuh database (dan menggunakan siklus server) jadi gunakanrequest
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 afollower_id
. Jadi GABUNG akan diaktifkan{$wpdb->posts}.post_author
sebagai kunci asing ke 'follower_id' di tabel 'user_relationship' Anda.sumber
Saya menjawab pertanyaan ini sangat terlambat dan permintaan maaf saya untuk hal yang sama. Saya sudah terlalu sibuk dengan tenggat waktu untuk mengurus ini.
Terima kasih banyak kepada @ m0r7if3r dan @kaiser dalam memberikan solusi dasar yang dapat saya sampaikan dan terapkan dalam aplikasi saya. Jawaban ini memberikan detail adaptasi saya terhadap solusi yang ditawarkan oleh @ m0r7if3r dan @kaiser.
Pertama, izinkan saya menjelaskan mengapa pertanyaan ini ditanyakan. Dari pertanyaan dan komentarnya, orang dapat menyimpulkan bahwa saya mencoba membuat WP_Query menarik semua pengguna (pemimpin) yang diikuti oleh pengguna tertentu (pengikut). Hubungan antara pengikut dan pemimpin disimpan dalam tabel khusus
follow
. Solusi paling umum untuk masalah ini adalah dengan menarik ID pengguna dari semua pemimpin pengikut dari tabel follow dan letakkan dalam array. Lihat di bawah:Setelah memiliki susunan pemimpin, Anda dapat meneruskannya sebagai argumen ke WP_Query. Lihat di bawah:
Solusi di atas adalah cara paling sederhana untuk mencapai hasil yang saya inginkan. Namun, ini tidak dapat diskalakan. Saat Anda memiliki pengikut yang mengikuti puluhan dan ribuan pemimpin, susunan ID pemimpin yang dihasilkan akan menjadi sangat besar dan memaksa situs WordPress Anda untuk menggunakan memori 100MB - 250MB pada setiap pemuatan halaman dan akhirnya menghancurkan situs. Solusi untuk masalah ini adalah menjalankan query SQL langsung pada database dan mengambil posting yang relevan. Saat itulah solusi @ m0r7if3r datang untuk menyelamatkan. Mengikuti rekomendasi @ kaiser saya berangkat untuk menguji kedua implementasi. Saya mengimpor sekitar 47 ribu pengguna dari file CSV untuk mendaftarkan mereka pada instalasi pengujian WordPress yang baru. Instalasi sedang menjalankan tema Twenty Eleven. Setelah ini saya menjalankan loop for untuk membuat sekitar 50 pengguna mengikuti setiap pengguna lainnya. Perbedaan waktu permintaan untuk solusi @kaiser dan @ m0r7if3r sangat mengejutkan. Solusi @ kaiser biasanya memakan waktu sekitar 2 hingga 5 detik untuk setiap permintaan. Variasi yang saya perkirakan terjadi ketika WordPress menyimpan cache untuk digunakan nanti. Di sisi lain solusi @ m0r7if3r menunjukkan waktu permintaan rata-rata 0,02 ms. Untuk menguji kedua solusi saya telah mengindeks ON untuk kolom leader_id. Tanpa pengindeksan ada peningkatan dramatis dalam waktu kueri.
Penggunaan memori saat menggunakan solusi berbasis array berdiri sekitar 100-150 MB dan turun menjadi 20 MB saat menjalankan SQL langsung.
Saya mengalami masalah dengan solusi @ m0r7if3r ketika saya harus meneruskan ID pengikut ke fungsi filter posts_where. Atleast, sesuai pengetahuan saya, WordPress tidak memungkinkan untuk melewatkan variabel ke fungsi filer. Anda dapat menggunakan variabel Global, tetapi saya ingin menghindari global. Saya akhirnya memperpanjang WP_Query untuk akhirnya mengatasi masalah ini. Jadi, inilah solusi terakhir yang saya terapkan (berdasarkan solusi @ m0r7if3r).
Catatan: Saya akhirnya mencoba solusi di atas dengan 1,2 juta entri di tabel ikuti. Waktu permintaan rata-rata sekitar 0,060 ms.
sumber
Anda dapat melakukan ini dengan solusi SQL sepenuhnya menggunakan
posts_where
filter. Berikut ini contohnya:Saya pikir mungkin ada cara untuk melakukan ini
JOIN
juga, tetapi saya tidak bisa memunculkannya. Saya akan terus bermain dengannya dan memperbarui jawabannya jika saya mendapatkannya.Bergantian, seperti yang disarankan @iser , Anda dapat membaginya menjadi dua bagian: mendapatkan pemimpin dan melakukan kueri. Saya merasa ini mungkin kurang efisien, tetapi tentu saja cara yang lebih mudah dimengerti. Anda harus menguji efisiensi sendiri untuk menentukan metode mana yang lebih baik, karena kueri SQL bersarang bisa menjadi sangat lambat.
DARI KOMENTAR:
Anda harus meletakkan fungsi di Anda
functions.php
dan melakukan yangadd_filter()
benar sebelumquery()
metodeWP_Query
dipanggil. Segera setelah itu, Anda harusremove_filter()
sehingga tidak mempengaruhi kueri lainnya.sumber
prepare()
. Semoga Anda tidak keberatan hasil edit. Dan ya: Kinerja memiliki untuk diukur dengan OP. Bagaimanapun: Saya masih berpikir ini seharusnya hanya usermeta dan bukan yang lain.functions.php
dan melakukan yangadd_filter()
benar sebelumquery()
metodeWP_Query
dipanggil. Segera setelah itu, Anda harusremove_filter()
sehingga tidak mempengaruhi kueri lainnya. Saya tidak yakin apa masalah penulisan ulang URL, saya telah menggunakanposts_where
banyak kesempatan dan tidak pernah melihat itu ...Tag Template
Cukup tempatkan kedua fungsi di
functions.php
file Anda . Kemudian sesuaikan fungsi 1 dan tambahkan nama tabel khusus Anda. Maka Anda perlu beberapa percobaan / kesalahan untuk menyingkirkan ID pengguna saat ini di dalam array yang dihasilkan (lihat komentar).Di dalam templat
Di sini Anda dapat melakukan apa pun yang Anda inginkan dengan hasil Anda.
sumber
JOIN
adalah jauh lebih mahal. Plus: Seperti yang saya sebutkan, kami tidak memiliki data uji, jadi silakan uji kedua jawaban dan beri kami pencerahan dengan hasil Anda.Inilah Kode OP dari komentar, untuk menambahkan set pertama pengguna uji. Saya harus dimodifikasi menjadi contoh dunia nyata.
Jawaban saya untuk tes ↑ ini:
Saya juga harus menyatakan bahwa ↑ pelacakan waktu di atas tidak dapat benar-benar diukur, karena juga akan memerlukan waktu untuk menghitung loop bersama. Lebih baik untuk mengulang melalui set ID yang dihasilkan dalam loop kedua.
proses selanjutnya di sini
sumber