WP_Queryを使用して、カテゴリごとに投稿が制限されている複数のカテゴリを照会しますか?

wordpress.stackexchange https://wordpress.stackexchange.com/questions/907

  •  16-10-2019
  •  | 
  •  

質問

15個の投稿に3つのカテゴリがあります。DBに1つのクエリを実行して、各カテゴリに最初の投稿が5つしか持っていきません。どうすればよいですか?

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

不可能な場合、より効率的なものは何ですか、親カテゴリのすべての投稿を取得し、それらをループするか、3つの異なるクエリを作成しますか?

役に立ちましたか?

解決

あなたが望むものは可能ですが、あなたが掘り下げる必要があります 可能な限り避けたい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 フィルターフック 次のように。注私はaを使用しています PHPヘレドック だから確信してください SQL; フラッシュが左にあります。また、グローバルVARを使用して、アレイにカテゴリスラグをリストすることで、フックの外側のカテゴリを定義できることに注意してください。このコードをプラグインまたはテーマに配置できます 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タイム3のクエリを行うことができるよりも?その場合は、WordPress APIを使用する他のオプションがあるかもしれません。

キャッシュにTransiments APIを使用する方が良いですか?

私はあなたの投稿がそれほど頻繁に変わらないと思います、正しいですか? 3つのクエリが定期的にヒットし、次に結果をキャッシュした場合はどうなりますか transients API?メンテナンス可能なコードと優れたパフォーマンスが得られます。より良いです UNION WordPressが投稿のリストをシリアル化された配列として1つのレコードに保存するため、上記のクエリ wp_options テーブル。

次の例を取り、Webサイトのルートにドロップすることができます。 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 代わりは。

お役に立てれば?

他のヒント

WP_Query() のようなものをサポートしていません 各猫の最初のx. 。それ以外の WP_Query() 使用できます get_posts() それぞれのカテゴリで、3回と言うこと:

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

$posts これで、各カテゴリの最初の5つの投稿が含まれています。

1つのクエリで各カテゴリの最初の5つの投稿を取得する方法がわかりません。 45の投稿しか持っていない場合は、データベースを一度押して、各カテゴリの5つの投稿を取得することがおそらく最も効率的なアプローチです。しかし、データベースを3回押して結果を組み合わせることは悪いことではありません。

ライセンス: CC-BY-SA帰属
所属していません wordpress.stackexchange
scroll top