it-swarm-id.com

Menggunakan WP_Query ke Query Beberapa Kategori dengan Posting Terbatas Per Kategori?

Saya memiliki 3 kategori dengan masing-masing 15 posting, saya ingin melakukan SATU permintaan ke db hanya membawa 5 posting pertama untuk setiap kategori, bagaimana saya bisa melakukannya?

$q = new WP_Query(array( 'post__in' => array(2,4,8), 'posts_per_page' => **FIRST_5_OF_EACH_CAT** ));

Dalam hal ini tidak mungkin, apa yang lebih efisien, mendapatkan semua posting untuk kategori induk dan mengulanginya atau membuat 3 pertanyaan yang berbeda?

10
Amit

Apa yang Anda inginkan adalah mungkin tetapi akan meminta Anda mempelajari SQL yang ingin saya hindari kapan pun memungkinkan (bukan karena saya tidak mengetahuinya, saya adalah pengembang SQL yang maju, tetapi karena in WordPress Anda ingin menggunakan API bila memungkinkan untuk meminimalkan masalah kompatibilitas di masa depan terkait dengan perubahan struktur database potensial di masa depan.)

SQL dengan operator UNION adalah Kemungkinan

Untuk menggunakan SQL yang Anda butuhkan adalah operator UNION dalam permintaan Anda, sesuatu seperti ini dengan asumsi siput kategori Anda adalah "category-1", "category-1" dan "category-3":

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
)

Anda dapat menggunakan SQL UNION dengan posts_join Filter

Dengan menggunakan di atas, Anda dapat langsung saja melakukan panggilan atau Anda dapat menggunakan posts_join filter hook seperti sebagai berikut; perhatikan saya menggunakan PHP heredoc jadi pastikan SQL; adalah flush left. Juga perhatikan saya menggunakan global var untuk memungkinkan Anda menentukan kategori di luar hook dengan mendaftar siput kategori dalam array. Anda dapat meletakkan kode ini di plugin atau di file functions.php tema Anda:

<?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 " ;
}

Tapi Bisa Ada Efek Samping

Tentu saja menggunakan kait modifikasi permintaan seperti posts_join selalu mengundang efek samping karena mereka bertindak secara global pada permintaan dan dengan demikian Anda biasanya perlu membungkus modifikasi Anda dalam if yang hanya menggunakannya ketika dibutuhkan dan kriteria apa yang akan diuji bisa rumit.

Berfokuslah pada Optimasi?

Namun, saya menganggap pertanyaan Anda yang bersangkutan adalah lebih banyak tentang optimasi daripada tentang mampu melakukan permintaan 5 kali 3 teratas, bukan? Jika demikian, mungkin ada opsi lain yang menggunakan WordPress API?

Lebih baik Menggunakan API Transien untuk Caching?

Saya menganggap posting Anda tidak akan sering berubah, benar? Bagaimana jika Anda menerima tiga (3) permintaan klik secara berkala dan kemudian cache hasilnya menggunakan Transients API ? Anda akan mendapatkan kode yang dapat dipelihara dan kinerja hebat; sedikit lebih baik daripada permintaan UNION di atas karena WordPress akan menyimpan daftar posting sebagai array serial dalam satu catatan dari tabel wp_options.

Anda dapat mengambil contoh berikut dan memasukkannya ke root situs web Anda sebagai test.php untuk menguji ini:

<?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);

Ringkasan

Sementara ya Anda bisa melakukan apa yang Anda minta menggunakan kueri SQL UNION dan kait filter posts_join Anda mungkin lebih baik menawarkan penggunaan caching denganTransients APIsebagai gantinya.

Semoga ini membantu?

15
MikeSchinkel

WP_Query() tidak mendukung sesuatu seperti X Pertama Untuk Setiap Kucing . Alih-alih WP_Query() Anda dapat menggunakan get_posts() pada masing-masing kategori Anda, jadi katakan tiga kali:

<?php
$posts      = array():
$categories = array(2,4,8);
foreach($categories as $cat) {
  $posts[] = get_posts('numberposts=5&offset=1&category='.$cat);
}
?>

$posts sekarang berisi lima posting pertama untuk setiap kategori.

1
hakre

Saya tidak tahu cara untuk mendapatkan lima posting pertama untuk masing-masing kategori dalam satu permintaan. Jika Anda hanya akan memiliki 45 posting, lalu tekan database sekali dan dapatkan lima posting Anda untuk setiap kategori mungkin merupakan pendekatan yang paling efisien. Memukul database tiga kali dan menggabungkan hasilnya bukanlah hal yang buruk.

0
Bernard Chen