Önemli feragatname: Bunu yapmanın doğru yolu tablonuzun yapısını değiştirmemek, wp_usermeta kullanmaktır. Daha sonra, yazılarınızı sorgulamak için herhangi bir özel SQL oluşturmanız gerekmez (yine de, örneğin Yönetici bölümünde, belirli bir amirine rapor veren herkesin listesini almak için bazı özel SQL'lere ihtiyacınız olacaktır). Bununla birlikte, OP özel SQL yazma hakkında sorular sorduğundan, özel SQL'i mevcut bir WordPress Sorgusu'na enjekte etmek için en iyi yöntem budur.
Karmaşık birleştirme yapıyorsanız, posts_where filtresini kullanamazsınız, çünkü birleşim, seçim ve muhtemelen grubu sorgunun bölümlerine göre veya sırayla değiştirmeniz gerekir.
En iyisi 'posts_clauses' filtresini kullanmak. Bu, WordPress çekirdeğindeki birçok kod satırı tarafından otomatik olarak oluşturulan SQL'in çeşitli bölümlerini eklemenize / değiştirmenize izin veren (kötüye kullanılmamalıdır!) Oldukça kullanışlı bir filtredir. Filtre geri arama imzası şudur:
function posts_clauses_filter_cb( $clauses, $query_object ){ }
ve geri dönmenizi bekler $clauses
.
Cümleler
$clauses
aşağıdaki anahtarları içeren bir dizidir; her anahtar doğrudan veritabanına gönderilen son SQL deyiminde kullanılacak olan bir SQL dizesidir:
- nerede
- GroupBy
- katılmak
- tarafından sipariş
- farklı
- alanlar
- sınırları
Veritabanına bir tablo ekliyorsanız (yalnızca post_meta, user_meta veya taksonomilerden kesinlikle yararlanamıyorsanız bunu yapın), muhtemelen, bu maddelerden daha fazlasına, örneğin, fields
"SELECT" seçeneğine dokunmanız gerekir. SQL deyiminin bir kısmı), join
("FROM" yan tümcesinde olanlar dışındaki tüm tablolarınız) ve belki de orderby
.
Cümleleri Değiştirme
Bunu yapmanın en iyi yolu, ilgili anahtarı $clauses
filtreden aldığınız diziden almanızdır :
$join = &$clauses['join'];
Şimdi, değiştirirseniz $join
, aslında doğrudan değiştireceksiniz, $clauses['join']
böylece değişiklikler $clauses
geri döndüğünde de olacak.
Orijinal Maddelerin Korunması
Şanslar (hayır, cidden, dinle), WordPress'in sizin için oluşturduğu mevcut SQL'i korumak isteyeceksiniz. Değilse, muhtemelen bakmak gerekirposts_request
filtreye - bu veritabanına gönderilmeden hemen önce tam mySQL sorgusu, bu yüzden tamamen kendiniz ile clobber edebilirsiniz. Bunu neden yapmak istiyorsun? Muhtemelen bilmiyorsun.
Yani, bentlerinde varolan SQL korumak amacıyla, (onlara atamak, yani maddeleri değil eklemeyi unutmayın: kullanım $join .= ' {NEW SQL STUFF}';
değil $join = '{CLOBBER SQL STUFF}';
. Not olduğu her eleman, çünkü $clauses
dizinin bir dizidir buna eklemek istiyorsanız, Muhtemelen başka herhangi bir karakter belirteçlerinden önce boşluk eklemek isteyeceksiniz, aksi halde muhtemelen bazı SQL sözdizimi hatası oluşturabilirsiniz.
Her bir maddede her zaman bir şeyler olacağını varsayabilir ve bu nedenle her yeni dizgiye bir boşlukla başladığınızı unutmayın:, $join .= ' my_table
veya, istediğiniz zaman, sadece bir boşluk ekleyen her zaman küçük bir satır ekleyebilirsiniz:
$join = &$clauses['join'];
if (! empty( $join ) ) $join .= ' ';
$join .= "JOIN my_table... "; // <-- note the space at the end
$join .= "JOIN my_other_table... ";
return $clauses;
Bu her şeyden çok stilistik bir şey. Hatırlanması gereken önemli nokta şudur: Zaten içinde bazı SQL olan bir cümle ekliyorsanız, dizginizden ÖNCE daima bir boşluk bırakın!
Bir araya koyarak
WordPress geliştirmenin ilk kuralı, kullanabildiğiniz kadar temel işlevsellik kullanmaya çalışmaktır. Gelecekte işinizi kanıtlamanın en iyi yolu budur. Çekirdek ekibin WordPress'in şimdi SQLite veya Oracle veya başka bir veritabanı dili kullanacağına karar verdiğini varsayalım. Elle yazılmış herhangi bir mySQL geçersiz olabilir ve eklentinizi veya temanızı bozabilir! WP'nin kendi başına mümkün olduğu kadar SQL üretmesine izin vermek ve ihtiyaç duyduğunuz bitleri eklemek daha iyidir.
Bu yüzden, ilk iş emri, WP_Query
temel sorgunuzdan mümkün olduğunca fazlasını elde etmenize yardımcı oluyor. Bunu yapmak için kullandığımız yöntem, büyük ölçüde bu yazı listesinin nerede görünmesi gerektiği ile ilgilidir. Sayfanın bir alt bölümü ise (ana sorgunuz değil) kullanırsınız get_posts()
; ana sorguysa, kullanabileceğinizi query_posts()
ve bununla yapılabileceğinizi varsayalım , ancak bunu yapmanın doğru yolu, ana sorguyu veritabanına çarpmadan önce (ve sunucu döngülerini tüketir) request
filtrelemektir.
Tamam, sorgunuzu oluşturdunuz ve SQL oluşturulmak üzere. Aslında, yaratıldı, veritabanına gönderilmedi. posts_clauses
Filtreyi kullanarak, çalışan ilişkileri tablosunuzu karışıma ekleyeceksiniz. Bu tabloya {$ wpdb-> prefix} diyelim. 'user_relationship' ve bu bir kesişim tablosu. (Bu arada, bu tablo yapısını genelleştirmenizi ve aşağıdaki alanlarla uygun bir kesişim tablosuna dönüştürmenizi öneririm: 'relationship_id', 'user_id', 'related_user_id', 'relationship_type'; bu çok daha esnek ve güçlüdür. .. ama dalıyorum).
Ne yapmak istediğinizi anlarsam, bir Liderin Kimliğini geçmek ve sadece o Liderin Takipçilerinin gönderilerini görmek istersiniz. Umarım doğru anlamışımdır. Doğru değilse, söylediklerimi almak ve ihtiyaçlarınıza göre uyarlamak zorunda kalacaksınız. Masa yapınıza bağlı kalacağım: a leader_id
ve a follower_id
. Dolayısıyla, JOIN, {$wpdb->posts}.post_author
'user_relationship' tablonuzdaki 'follower_id' için yabancı bir anahtar olarak kullanılacaktır.
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;
}