Her 15 gönderide 3 kategorim var, db'ye ONE sorgulamak istiyorum, her kategori için sadece 5 ilk gönderi getirdim, nasıl yapabilirim?
$q = new WP_Query(array( 'post__in' => array(2,4,8), 'posts_per_page' => **FIRST_5_OF_EACH_CAT** ));
Bunun mümkün olmadığı durumlarda, ana kategori için tüm gönderileri almak ve aralarında dolaşmak ya da 3 farklı sorgu oluşturmak için daha etkili olan nedir?
İstediğiniz mümkün ancak mümkün olduğunda kaçınmayı sevdiğim SQL'e girmenizi gerektirecek (bilmediğim için değil, ileri düzeyde bir SQL geliştiricisiyim, çünkü in WordPress, mümkün olduğunda API kullanmak istediğinizde gelecekteki potansiyel veritabanı yapısı değişiklikleriyle ilgili gelecekteki uyumluluk sorunlarını en aza indirmek için.)
UNION
ile SQL Operatör Olasılıktırİhtiyacınız olan SQL'i kullanmak için sorgunuzdaki bir UNION
işleci olarak, kategori sümüklü böceklerinizin "category-1"
, "category-1"
ve "category-3"
olduğunu farz edelim:
SELECT * FROM wp_posts WHERE ID IN (
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-1'
LIMIT 5
UNION
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-2'
LIMIT 5
UNION
SELECT tr.object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='category-3'
LIMIT 5
)
posts_join
Filtresi ile kullanabilirsinizYukarıdakileri kullanarak sadece çağrıyı doğrudan yapabilirsiniz veya şunları yapabilirsiniz: bir posts_join
filtre kancası kullanın aşağıdaki gibi; note Not Bir PHP heredoc kullanıyorum, bu nedenle SQL;
dosyasının tamamen solabildiğinden emin olun. Ayrıca, bir dizideki kategori öbeklerini listeleyerek kanca dışındaki kategorileri tanımlamanıza izin vermek için global bir var kullandığımı unutmayın. Bu kodu bir eklentiye veya temanızın functions.php
dosyasına koyabilirsiniz:
<?php
global $top_5_for_each_category_join;
$top_5_for_each_category_join = array('category-1','category-2','category-3');
add_filter('posts_join','top_5_for_each_category_join',10,2);
function top_5_for_each_category_join($join,$query) {
global $top_5_for_each_category_join;
$unioned_selects = array();
foreach($top_5_for_each_category_join as $category) {
$unioned_selects[] =<<<SQL
SELECT object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='{$category}'
LIMIT 5
SQL;
}
$unioned_selects = implode("\n\nUNION\n\n",$unioned_selects);
return $join . " INNER JOIN ($unioned_selects) categories ON wp_posts.ID=categories.object_id " ;
}
Tabii ki, posts_join
gibi sorgu modifikasyon kancalarını kullanmak, her zaman sorgulara global olarak etki etmeleri için yan etkilere neden olur ve bu nedenle de değişikliklerinizi genellikle yalnızca gerektiğinde kullanan bir if
içine sarmanız ve hangi ölçütleri zor bulacağınıza karar vermeniz gerekir.
Ancak, sorunuzun endişe duyduğunu varsayalım: optimizasyon hakkında daha fazla ilk 5 kez 3 sorgulama yapmaktan daha fazlası, değil mi? Bu durumda, WordPress API'sini kullanan başka seçenekler de olabilir mi?
Gönderilerinizin bu kadar sık değişmeyeceğini varsayıyorum, doğru mu? Üç (3) sorgunun belirli aralıklarla isabetini kabul ederseniz ve Transients API kullanarak sonuçları önbelleğe alırsanız ne olur? Bakım kodu ve mükemmel performans elde edersiniz; yukarıdaki UNION
sorgusundan daha iyi bir nokta çünkü WordPress, yazı listelerini wp_options
tablosunun bir kaydında serileştirilmiş bir dizi olarak saklar.
Bunu test etmek için aşağıdaki örneği alabilir ve web sitenizin kök dizinine test.php
olarak bırakabilirsiniz:
<?php
$timeout = 4; // 4 hours
$categories = array('category-1','category-2','category-3');
include "wp-load.php";
$category_posts = get_transient('top5_posts_per_category');
if (!is_array($category_posts) || count($category_posts)==0) {
echo "Hello Every {$timeout} hours!";
$category_posts = array();
foreach($categories as $category) {
$posts = get_posts("post_type=post&numberposts=5&taxonomy=category&term={$category}");
foreach($posts as $post) {
$category_posts[$post->ID] = $post;
}
}
set_transient('top5_posts_per_category',$category_posts,60*60*$timeout);
}
header('Content-Type:text/plain');
print_r($category_posts);
Evet, bir SQL UNION
sorgusu ve posts_join
filtre kancası kullanarak istediğiniz şeyi yapabilirsiniz, bunun yerineGeçici APIile önbelleğe alma özelliğini kullanabilirsiniz.
Bu yardımcı olur umarım?
WP_Query()
, Her Kedi İçin İlk X gibi bir şeyi desteklemez. WP_Query()
yerine, kategorilerinizin her birinde get_posts()
kullanabilirsiniz, böylece üç kez:
<?php
$posts = array():
$categories = array(2,4,8);
foreach($categories as $cat) {
$posts[] = get_posts('numberposts=5&offset=1&category='.$cat);
}
?>
$posts
şimdi her kategori için ilk beş gönderiyi içeriyor.
Her kategori için ilk beş yazıyı tek bir sorguda almanın bir yolunu bilmiyorum. Yalnızca 45 gönderiye sahip olacaksanız, veritabanına bir kez vurmak ve her kategori için beş gönderi almak muhtemelen en etkili yaklaşımdır. Veritabanına üç kez basmak ve sonuçları birleştirmek de kötü bir şey değil.