私はこのようなことを達成したいのですが、それが可能であるかどうか、そしてそれを実行するための最良の方法が何であるかわかりません。
私が投稿を照会する方法は、次のとおりです。
<div class="post">
<?php global $wp_query;
query_posts( array('post_type' => array( 'lecturas-post' ),'showposts' => 15, 'paged'=>$paged, 'order' => 'DESC' ));?>
<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
<div><?php the_title() ?></a>
<?php endwhile; // end of the loop. ?>
</div>
誰が私にそれをするための方法や最善の方法についてのヒントを与えることができますか?
コメントで述べたように、1回のクエリでこれを実行できます。ここでの原則は、前の投稿の投稿日の月が前の投稿の月と一致しない場合にのみ日付の見出しを表示することです。
始める前に、いくつか注意してください。
絶対に query_posts
を使用しないでください。ただし、実際にページ上のすべての情報を分割する必要がある場合は除きます。それは単にメインクエリを再実行してそれを壊すだけでなく、ページネーションとあなたのグローバルをめちゃくちゃにし、そしてまたあなたの問い合わせられたオブジェクト関数とめちゃくちゃにします。本当にカスタムクエリを実行する必要がある場合は、WP_Query
またはget_posts
を使用してください。
showposts
はposts_per_page
のために数年前にドロップされました
グローバルな$wp_query
を利用する必要はありません。 query_posts
はとにかくそれをめちゃくちゃにします
投稿は、最新の投稿が最初に、最も古い投稿が最後に時系列順に配信されるため、すでに正しい順番になっています。適切な場所に日付を表示するだけです。
これを行うには、現在の投稿の投稿日から現在の月と年を取得し、それを前の投稿の投稿日の月と比較して、月が一致しない場合は日付を表示するだけです。一致すれば表示する
説明として、メインクエリでメインループを使用します。
これを達成するために、あなたはする必要があります:
現在の投稿の投稿日から月を取得します。これを実現するには、get_the_date( 'F' )
を使います
ループ内の前の投稿を$wp_query->posts['this will be current post -1 ']->post
で取得します。
2つの投稿の間の月を取得および比較する
比較に従って日付を表示または非表示
このコードは、while()
ステートメントの直後、ループの内側に入ります。
$current_month = get_the_date('F');
if( $wp_query->current_post === 0 ) {
the_date( 'F Y' );
}else{
$f = $wp_query->current_post - 1;
$old_date = mysql2date( 'F', $wp_query->posts[$f]->post_date );
if($current_month != $old_date) {
the_date( 'F Y' );;
}
}
カスタムクエリを実行する必要がある場合は、これを試してください。
$q = new WP_Query( array('post_type' => array( 'lecturas-post' ),'posts_per_page' => 15, 'paged'=>$paged, 'order' => 'DESC' ));
if( $q->have_posts() ) {
while( $q->have_posts() ) {
$q->the_post();
$current_month = get_the_date('F');
if( $q->current_post === 0 ) {
the_date( 'F Y' );
}else{
$f = $q->current_post - 1;
$old_date = mysql2date( 'F', $q->posts[$f]->post_date );
if($current_month != $old_date) {
the_date( 'F Y' );;
}
}
the_title();
}
}
以下の@PieterGoosenからのコメントを検討した後、単一のクエリを使用してあなたの目的を達成する方法を追加しました。
私はメソッドをベンチマークしました、そして 複数のクエリメソッドはおよそ15%遅くなりました 。余計な余裕はありませんが、少しでも役立つので、正直に言うとメソッドはさらに洗練されたものになるでしょう。
私は繁栄のために答えの中に複数の問い合わせ方法を残しました、しかし私は単一の問い合わせ方法が使われることを勧めます。
シングルクエリ方式
$time_start = microtime(true);
/** Set up a date interval object for 6 monts ago (you can change as required) */
$interval = new DateInterval('P6M');
$interval->invert = 1;
/** Grab the date as it was 6 months ago */
$date = new DateTime(date('Y-m-d'));
$date->add($interval);
/** Query the database for all posts newer than the the given date interval */
$args = array(
'nopaging' => true,
'posts_per_page' => -1,
'post_type' => 'post',
'post_status' => 'publish',
'order_by' => 'date',
'date_query' => array(
'after' => $date->format('Y-m-d')
)
);
$month_query = new WP_Query($args);
/** Check to ensure that there are articles for this month... */
if($month_query->have_posts()) :
$month_titles = array();
$close_ul = false;
//echo '<ul style="padding-left: 250px;" id="monthly-posts">';
/** Set the attributes for displaying the title as an attribute */
$title_attribute_args = array(
'before' => 'Visit article \'',
'after' => '\' ',
'echo' => false
);
/** Loop through each post for this month... */
while($month_query->have_posts()) : $month_query->the_post();
/** Check the month/year of the current post */
$month_title = date('F Y', strtotime(get_the_date('Y-m-d H:i:s')));
/** Maybe output a human friendly date, if it's not already been output */
if(!in_array($month_title, $month_titles)) :
if($close_ul) echo '</ul>'; // Check if the unordered list of posts should be closed (it shouldn't for the first '$monthe_title')
echo '<h1 style="padding-left: 250px;" id="monthly-title">' . $month_title . '</h1>'; // Output the '$month_title'
echo '<ul style="padding-left: 250px;" id="monthly-posts">'; // Open an unordered lists for the posts that are to come
$month_titles[] = $month_title; // Add this `$month_title' to the array of `$month_titles` so that it is not repeated
$close_ul = true; // Indicate that the unordered list should be closed at the next oppurtunity
endif;
/** Output each article for this month */
printf(
'<li id="monthly-post-%1$s">%2$s <a href="%3$s" title="%4$s">%3$s</a></li>',
get_the_ID(), /** %1$s - The ID of the post */
get_the_title(), /** %2$s - The article title */
get_permalink(get_the_ID()), /** %3$s - The article link */
the_title_attribute($title_attribute_args) /** %4$s - The title for use as an attribute */
);
endwhile;
if($close_ul) echo '</ul>'; // Close the last unordered list of posts (if there are any shown)
endif;
/** Reset the query so that WP doesn't do funky stuff */
wp_reset_query();
これを試してみてください。私は、過去6か月だけが選択され、各月の最後の5つの投稿のみが選択されるように設定しましたが、あなたは好きなようにそれを変更することができます。
基本的に、コードは最初にどの月に投稿があるのかを確認してから、その月の最後の5つの投稿をリンクと共に出力します。
複数クエリ方式
global $wpdb, $wp_locale;
/** Query the individual months to display (I've chosen the last 6 months) */
$query = $wpdb->prepare('
SELECT DISTINCT YEAR(`%1$s`.`post_date`) AS year, MONTH(`%1$s`.`post_date`) AS month
FROM `%1$s`
WHERE `%1$s`.`post_type` = "post"
ORDER BY `%1$s`.`post_date` DESC
LIMIT 6',
$wpdb->posts
);
$months = $wpdb->get_results($query);
/** Count the number of months */
$month_count = count($months);
/** Ensure that there are months to display... */
if($month_count || ($month_count === 1 && $months[0]->month > 0)) :
/** Loop through each month... */
foreach($months as $month) :
if($month->year === 0) :
continue;
endif;
/** Grab the individual month and year, and construct a human friendly date (for the title) */
$m = zeroise($month->month, 2);
$y = $month->year;
$human_date = sprintf(__('%1$s %2$d'), $wp_locale->get_month($m), $y);
/** Grab any posts for this month (I've chosedn only the last 5 posts) */
$args = array(
'nopaging' => true,
'posts_per_page' => 5,
'post_type' => 'post',
'post_status' => 'publish',
'order_by' => 'date',
'year' => $y,
'monthnum' => $m
);
$month_query = new WP_Query($args);
/** Check to ensure that there are articles for this month... */
if($month_query->have_posts()) :
/** Output a human friendly date */
echo '<h1 id="monthly-title">' . $human_date . '</h1>';
echo '<ul id="monthly-posts">';
/** Set the attributes for displaying the title as an attribute */
$title_attribute_args = array(
'before' => 'Visit article \'',
'after' => '\' ',
'echo' => false
);
/** Loop through each post for this month... */
while($month_query->have_posts()) : $month_query->the_post();
/** Output each article for this month */
printf(
'<li id="monthly-post-%1$s">%2$s <a href="%3$s" title="%4$s">%3$s</a></li>',
get_the_ID(), /** %1$s - The ID of the post */
get_the_title(), /** %2$s - The article title */
get_permalink(get_the_ID()), /** %3$s - The article link */
the_title_attribute($title_attribute_args) /** %4$s - The title for use as an attribute */
);
endwhile;
echo '</ul>';
endif;
/** Reset the query so that WP doesn't do funky stuff */
wp_reset_query();
endforeach;
endif;
これは、特定の年/月、または当年の前後に、投稿またはカスタム投稿の種類のデータを取得するために、一般的なニーズに合わせて使用した関数です。
// you could change the name in case it collides with some other plugin
function get_posts_by_date($user_options = array()){
$options = array(
'year_limit' => '1980'
,'month_limit' => '01'
,'operator' => '>=' // date comparison operator
,'current_year' => true // limit data to current year
,'post_type' => 'post'
,'year_order' => 'DESC'
,'month_order' => 'DESC'
,'post_ids_order' => 'DESC'
,'raw_output' => false
);
extract(array_merge($options, $user_options));
global $wpdb;
if($operator == '>=' || $operator == '=='){
$day = "01";
} elseif($mode == '<='){
$day = "31";
}
if($current_year){ // will be after [previous year]/12/31
$year_limit = date('Y', strtotime('-1 year'));
$month_limit = '12';
$day = "31";
$operator == '>=';
}
// warning: if your parameters come from user input/forms,
// pass them using $wpdb::prepare()
// https://developer.wordpress.org/reference/classes/wpdb/prepare/
$results = $wpdb->get_results("
SELECT tbl.y year, group_concat(month_posts ORDER BY tbl.m " . $month_order . " SEPARATOR '-') months
FROM (
SELECT YEAR(p.post_date) y, MONTH(p.post_date) m, concat(MONTH(p.post_date), ':', group_concat(p.id ORDER BY p.post_date " . $post_ids_order . " )) month_posts
FROM $wpdb->posts p
WHERE (p.post_status = 'publish' OR p.post_status = 'future')
AND p.post_type = '" . $post_type . "'
AND p.post_date " . $operator . " DATE('" . $year_limit . "-" . $month_limit . "-" . $day . " 00:00:00')
GROUP BY y, m
) tbl
GROUP BY tbl.y
ORDER BY tbl.y " . $year_order
);
if($raw_output) return $results;
global $wp_locale;
foreach ($results as $data){
$months_data = explode('-',$data->months);
$months = array();
$data->count = 0; // year count
foreach ($months_data as $month_data){
$month_obj = new stdClass;
$splitted = explode(':',$month_data);
$raw_month = $splitted[0];
$month_obj->number = $raw_month;
$month_obj->name = $wp_locale->get_month($raw_month);
$month_obj->posts = array();
$post_ids = explode(',',$splitted[1]);
$data->count += count($post_ids);
foreach($post_ids as $post_id){
$month_obj->posts[] = get_post($post_id);
$months[$raw_month] = $month_obj;
}// foreach
}// foreach
$data->months = $months;
}// foreach
return $results;
}// get_posts_by_date
使用例
$posts_by_date = get_posts_by_date(array(
'year_limit' => '2016'
,'operator' => '<='
,'current_year' => false
,'post_type' => 'product'
,'month_order' => 'ASC'
,'raw_output' => true
));
raw_output
オプションがtrueの場合、デフォルトの出力は次のようになります。
array(2) {
[0]=>
object(stdClass)#6645 (2) {
["year"]=>
string(4) "2017"
["months"]=>
string(65) "8:386,401-7:406,373,380,377,408,399,362-6:1,391,404-5:367,397,394"
}
[1]=>
object(stdClass)#6644 (2) {
["year"]=>
string(4) "2016"
["months"]=>
string(5) "6:429"
}
}
「月」文字列には、次の形式の値が含まれています。
month:[post ids]-month:[post ids]-ecc
raw_output
オプションがfalseの場合は、次のような投稿の一覧が表示されます。
array (array of objects)
object
-> year (ex. '2017')
-> count (total year's posts)
-> months (array of objects)
month
-> number (of month)
-> name (localized)
-> posts (array of post objects)
ハッピーコーディング... :)