it-swarm.asia

Kategori Başına Sınırlı Gönderi ile Birden Çok Kategoriyi Sorgulamak için WP_Query Kullanımı?

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?

10
Amit

İ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.)

UNIONile SQL Operatör Olasılıktır

İhtiyacınız olan SQL'i kullanmak için sorgunuzdaki bir UNIONiş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
)

SQL UNION'ı posts_join Filtresi ile kullanabilirsiniz

Yukarı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 " ;
}

Fakat Yan Etkiler Olabilir

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 ifiçine sarmanız ve hangi ölçütleri zor bulacağınıza karar vermeniz gerekir.

Bunun yerine Optimizasyona Odaklanmak mı?

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?

Önbellekleme için Geçici API'leri Kullanmak Daha İyi 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 UNIONsorgusundan 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);

Özet

Evet, bir SQL UNIONsorgusu 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?

15
MikeSchinkel

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.

1
hakre

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.

0
Bernard Chen