it-swarm.asia

استخدام WP_Query للاستعلام عن فئات متعددة مع مشاركات محدودة لكل فئة؟

لدي 3 فئات مع كل 15 وظيفة ، أريد أن أفعل استعلام واحد إلى ديسيبل جلب 5 وظائف الأولى فقط لكل فئة ، كيف يمكنني القيام بذلك؟

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

في حال لم يكن ذلك ممكنًا ، فما هو الأكثر كفاءة ، الحصول على جميع منشورات الفئة الأصل والتكرار من خلالها أو إنشاء 3 استعلامات مختلفة؟

10
Amit

ما تريده ممكن ولكن سيتطلب منك البحث في SQL التي أحب تجنبها كلما كان ذلك ممكنًا (ليس لأنني لا أعرف ذلك ، أنا مطور SQL متقدم ، لكن بسبب في WordPress الذي تريد استخدامه لواجهة برمجة التطبيقات (API) كلما كان ذلك ممكنًا لتقليل مشكلات التوافق المستقبلية المتعلقة بتغيرات هيكل قاعدة البيانات المحتملة في المستقبل.)

SQL مع عامل التشغيل UNION هو إمكانية

لاستخدام SQL ما تحتاجه هو عامل UNION في استعلامك ، شيء من هذا القبيل بافتراض أن الرخويات الفئة الخاصة بك هي "category-1" و "category-1" و "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
)

يمكنك استخدام SQL UNION مع عامل تصفية posts_join

باستخدام ما سبق ، يمكنك إما فقط إجراء المكالمة مباشرة أو يمكنك استخدام ربط مرشح posts_joinمثل كما يلي ؛ لاحظ أنني أستخدم PHP heredoc لذلك تأكد من SQL; اليسار. لاحظ أيضًا أنني استخدم متغيرًا عالميًا للسماح لك بتحديد الفئات الموجودة خارج الخطاف من خلال سرد فئات الرخويات في صفيف. يمكنك وضع هذا الرمز في مكون إضافي أو في ملف functions.php الخاص بموضوعك:

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

ولكن يمكن أن يكون هناك آثار جانبية

بطبيعة الحال ، فإن استخدام ربط تعديل الاستعلام مثل posts_join يدعو دائمًا إلى آثار جانبية من حيث أنها تعمل على مستوى العالم في الاستعلامات وبالتالي تحتاج عادة إلى التفاف تعديلاتك في if الذي يستخدمه فقط عند الحاجة والمعايير التي يمكن اختبارها يمكن أن تكون خادعة.

التركيز على التحسين بدلا من ذلك؟

ومع ذلك ، أفترض أن سؤالك يشعر بالقلق هو المزيد عن التحسين أكثر من كونه قادرًا على القيام باستعلام أعلى 5 مرات ، أليس كذلك؟ إذا كانت هذه هي الحالة فربما هناك خيارات أخرى تستخدم واجهة برمجة تطبيقات WordPress؟

من الأفضل استخدام واجهة برمجة تطبيقات العابر للتخزين المؤقت؟

أفترض أن مشاركاتك لن تغير ذلك كثيرًا ، صحيح؟ ماذا لو قبلت الاستعلام الثلاثة (3) الذي تم ضربه بشكل دوري ثم قم بتخزين النتائج مؤقتًا باستخدام Transients API ؟ ستحصل على رمز يمكن الحفاظ عليه وأداء رائع ؛ أفضل قليلاً من استعلام UNION أعلاه لأن WordPress سيخزن قوائم المنشورات كصفيف مسلسل في سجل واحد من جدول wp_options.

يمكنك أخذ المثال التالي والإفلات من جذر موقع الويب الخاص بك كـ test.php لاختبار ذلك:

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

ملخص

أثناء الإجابة بنعم ، يمكنك القيام بما طلبت باستخدام استعلام SQL UNION وربط عامل التصفية posts_join الذي من المحتمل أن تقدمه بشكل أفضل باستخدام التخزين المؤقت معTransients APIبدلاً من ذلك.

أتمنى أن يساعدك هذا؟

15
MikeSchinkel

WP_Query() لا يدعم شيئًا مثل X الأول لكل Cat . بدلاً من WP_Query()- يمكنك استخدام get_posts() في كل فئة من فئاتك ، وذلك ليقول ثلاث مرات:

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

يحتوي $posts الآن على أول خمس مشاركات لكل فئة.

1
hakre

لا أعرف طريقة للحصول على أول خمس مشاركات لكل فئة من الفئات في استعلام واحد. إذا لم يكن لديك سوى 45 منشورًا ، فمن المحتمل أن يكون ضرب قاعدة البيانات مرة واحدة والحصول على خمس وظائف لكل فئة هو الطريقة الأكثر فعالية. إن ضرب قاعدة البيانات ثلاث مرات والجمع بين النتائج ليس بالأمر السيئ.

0
Bernard Chen