私は自分のホームページに「最新の投稿」と「人気の投稿」のセクションを作成するためにWP_Queryを使っています。私はちょうど2つのカテゴリ(9と11)から5つの投稿を引き出そうとしていますが、それは猫9からの投稿のみを表示します。
これが私が「最新の投稿」に使っているphpです -
<ul>
<?php
$cat = array(9,11);
$showposts = 5;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args=array(
'category__in' => $cat,
'showposts' => $showposts,
'paged' => $paged,
'orderby' => 'post_date',
'order' => 'DESC',
'post_status' => 'publish',
);
$the_query = new WP_Query ( $args ); //the query
$i = 0;while ($the_query->have_posts() ) : $the_query->the_post(); //start the loop
?>
<?php
if($i==0){ //Sets the output for the top post
?>
<li class="first-news">
<div class="post-thumbnail"><a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(350,187); ?></a></div>
<h2 class="post-box-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<p class="post-meta"><span class="tie-date"><?php the_time('F jS, Y') ?></span></p>
<div class="entry"><?php the_excerpt(); ?></div>
<div><a class="more-link" href="<?php the_permalink(); ?>">Read More »</a></div>
</li>
<?php
$i++;
} else { ?>
<li class="other-news rar">
<div class="post-thumbnail"><a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(145,93); ?></a></div>
<h3 class="post-box-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<p class="post-meta"><span class="tie-date"><?php the_time('F jS, Y') ?></span></p>
</li>
<?php } endwhile; //end of the loop ?>
<?php wp_reset_postdata(); // reset the query ?>
</ul>
助言がありますか?
'posts_*'
/'posts_request'
と組み合わせて'posts_where'
フィルタ(str_replace
、preg_replace
...)を使用した経験では、信頼性が低く、柔軟性がありません。
他のフィルタ変更がそのフィルタの1つを使用すると、予想外の結果が得られ、最悪の場合はSQLエラーが発生するため、信頼性が低いため信頼できません。
議論を変えるので柔軟性がない、例えばカテゴリの場合は 'include_children'、それ以外の場合はコードを再利用します。 2の代わりに3の用語は多くの作業を必要とします。
さらに、コードを互換性があるように調整するには、SQLを手動で編集する必要があります。
そのため、パフォーマンスに関して最善の解決策ではないにしても、ときには、より標準的な _アプローチが最善かつより柔軟なアプローチになることがあります。
そして、パフォーマンスはいくつかのキャッシングトリックで向上させることができます...
私の提案:
usort
を使用して、異なるクエリからの投稿を順序付けるための関数を作成します(たとえば、用語ごとに1つ)。まず投稿を注文する関数:
function my_date_terms_posts_sort( Array $posts, $order = 'DESC' ) {
if ( ! empty( $posts ) ) {
usort( $posts, function( WP_Post $a, WP_Post $b ) use ( $order ) {
$at = (int) mysql2date( 'U', $a->post_date );
$bt = (int) mysql2date( 'U', $b->post_date );
$orders = strtoupper($order) === 'ASC' ? array( 1, -1 ) : array( -1, 1 );
return $at === $bt ? 0 : ( $at > $bt ) ? $orders[0] : $orders[1];
} );
}
return $posts;
}
そして、キャッシュされない関数は次のようになります。
function my_fresh_terms_get_posts( $args, $terms, $tax_query_args = NULL ) {
$posts = array();
// we need to know at least the taxonomy
if ( ! is_array( $tax_query_args ) || ! isset( $tax_query_args['taxonomy'] ) ) return;
// handle base tax_query
$base_tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
// run a query for each term
foreach ( $terms as $term ) {
$term_tax_query = wp_parse_args( array(
'terms' => array( $term ),
'field' => is_numeric( $term ) ? 'term_id' : 'slug'
), $tax_query_args );
$args['tax_query'] = array_merge( $base_tax_query, array($term_tax_query) );
$q = new WP_Query( $args );
if ( $q->have_posts() ) {
// merging retrieved posts in $posts array
// preventing duplicates using ID as array keys
$ids = wp_list_pluck( $q->posts, 'ID' );
$keyed = array_combine( $ids, array_values( $q->posts ) );
$posts += $keyed;
}
}
return $posts;
}
キャッシュをチェックし、利用可能であればそれを返すか、キャッシュされていない結果を返すようになりました。
function my_terms_get_posts( $args, $terms, $tax_query_args = NULL, $order = 'DESC' ) {
// we need to know at least the taxonomy
if ( ! is_array( $tax_query_args ) || ! isset( $tax_query_args['taxonomy'] ) ) return;
$tax = $tax_query_args['taxonomy'];
// get cached results
$cached = get_transient( "my_terms_get_posts_{$tax}" );
if ( ! empty( $cached ) ) return $cached;
// no cached results, get 'fresh' posts
$posts = my_fresh_terms_get_posts( $args, $terms, $tax_query_args );
if ( ! empty($posts) ) {
// order posts and cache them
$posts = my_date_terms_posts_sort( $posts, $order );
set_transient( "my_terms_get_posts_{$tax}", $posts, DAY_IN_SECONDS );
}
return $posts;
}
キャッシュは毎日自動クリーンアップされます ただし、特定の分類法の新しい投稿が追加または更新されるたびにキャッシュを無効にすることができます。それは'set_object_terms'
にクリーンキャッシュ機能を追加することで実行できます
add_action( 'set_object_terms', function( $object_id, $terms, $tt_ids, $taxonomy ) {
$taxonomies = get_taxonomies( array( 'object_type' => array('post') ), 'names' );
if ( in_array( $taxonomy, (array) $taxonomies ) ) {
delete_transient( "my_terms_get_posts_{$taxonomy}" );
}
}, 10, 4 );
// the number of post to retrieve for each term
// total of posts retrieved will be equat to this number x the number of terms passed
// to my_terms_get_posts function
$perterm = 5;
// first define general args:
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$args = array(
'posts_per_page' => $perterm,
'paged' => $paged,
);
// taxonomy args
$base_tax_args = array(
'taxonomy' => 'category'
);
$terms = array( 9, 11 ); // is also possible to use slugs
// get posts
$posts = my_terms_get_posts( $args, $terms, $base_tax_args );
// loop
if ( ! empty( $posts ) ) {
foreach ( $posts as $_post ) {
global $post;
setup_postdata( $_post );
//-------------------------> loop code goes here
}
wp_reset_postdata();
}
関数は、追加の分類法に対するクエリでさえも複雑なクエリを使用するのに十分なほど柔軟です。
例えば。
$args = array(
'posts_per_page' => $perterm,
'paged' => $paged,
'post_status' => 'publish',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'another_taxonomy',
'terms' => array( 'foo', 'bar' ),
'field' => 'id'
)
)
);
$base_tax_args = array(
'taxonomy' => 'category',
'include_children' => FALSE
);
$terms = array( 'a-category', 'another-one' );
$posts = my_terms_get_posts( $args, $terms, $base_tax_args );
このようにして、$args
配列内の各用語について、$base_tax_args
配列内に設定された 'tax_query'が、$terms
内のtax query引数と動的にマージされます。
昇順のオーダーポストも可能です:
$posts = my_terms_get_posts( $args, $terms, $base_tax_args, 'ASC' );
ご注意ください:
いくつかのカテゴリからの投稿を表示 (カテゴリIDを使用してこれらのカテゴリを持つ投稿を表示):
$query = new WP_Query( 'cat=9,11' );
そして、コーデックスのページ付けパラメータによると、'showposts'
は非推奨で'posts_per_page'
に置き換えられています。
posts_per_page
(int) - 1ページに表示する投稿数( バージョン2.1 で使用可能、showposts
パラメータに置き換え).
あなたが求めているのは、この質問のほぼ複製です: posts_where/posts_joinを使用して独自のネストされたmeta_queryを作成するにはどうすればよいですか?
問題は、@ fischiが示唆しているように、結果がいずれかのカテゴリからのものであり、両方が等しく表される前に投稿制限に達することです。これを機能させるには、UNIONが必要です。 WP_Query
はそのロジックに対応していませんが、フックを使用して機能させることができます。
$cat = 9; // your first category
$showposts = 5; // actual results are twice this value
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args=array(
'cat' => $cat,
'posts_per_page' => $showposts,
'paged' => $paged,
'orderby' => 'post_date',
'order' => 'DESC',
'post_status' => 'publish',
);
function create_cat_union($clauses) {
remove_filter('posts_request','create_cat_union',1);
$clauses = str_replace('SQL_CALC_FOUND_ROWS','',$clauses,$scfr);
$scfr = (0 < $scfr) ? 'SQL_CALC_FOUND_ROWS' : '';
$pattern = 'wp_term_relationships.term_taxonomy_id IN \(([0-9,]+)\)';
$clause2 = preg_replace('|'.$pattern.'|','wp_term_relationships.term_taxonomy_id IN (11)',$clauses); // manipulate this
return "SELECT {$scfr} u.* FROM (({$clauses}) UNION ({$clause2})) as u";
}
add_filter('posts_request','create_cat_union',1,2);
$the_query = new WP_Query ( $args ); //the query
var_dump($the_query->posts);
いくつかのメモ:WP_Query
はカテゴリ引数を解析し、最初のUNION
がカテゴリ9のすべての子を含むようにカテゴリの子を検索します。Idid notカテゴリ11のロジックを複製します。その機能が必要な場合は、 WP_Query
source を参照できます。 =効果を再現します。