Я хочу заказать сообщения WordPress последним комментарием. Насколько мне известно, это невозможно с использованием объекта WP_Query, и для него потребуется пользовательский запрос $ wpdb, который я могу легко написать. Однако я не знаю, как настроить цикл для запуска этого объекта.
Может ли кто-нибудь помочь?
Хорошо, парни,
Здесь много замечательных ответов, но, очевидно, никто не успел их протестировать.
Хао Лян получает кредит на первый лучший оригинальный ответ, но, к сожалению, его код не показывает сообщения без комментариев.
Капитан Кейтар находится на правильном пути, но его код будет отображать каждый отдельный пост и вложение в виде отдельного результата.
Вот модифицированная версия Captain Keytar, но она ограничивает результаты типом «post» .., который был опубликован (чтобы избежать получения черновиков!)
select wp_posts.*, coalesce( ( select max(comment_date) from $wpdb->comments wpc where wpc.comment_post_id = wp_posts.id ), wp_posts.post_date ) as mcomment_date from $wpdb->posts wp_posts where post_type = 'post' and post_status = 'publish' order by mcomment_date desc limit 10
приписывать
select wp_posts.*, max(comment_date) as max_comment_date from $wpdb->posts wp_posts right join $wpdb->comments on id = comment_post_id group by ID order by max_comment_date desc limit 10
к некоторому переменному $ query. Вы можете играть с помощью 10 или самого запроса. (Я не ниндзя оптимизации SQL). Тогда ваш код будет выглядеть примерно так:
<?php $results = $wpdb->get_results($query) or die('!'); foreach ($results as $result): ?> [insert template here] <?php endforeach ?>
Этот шаблон более подробно рассматривается Кодексом .
Я использовал более простую часть встроенной функции WP. надеюсь, что это поможет, и кто-то может продолжать развиваться. Вот упрощенная версия, которая показывает название и выдержку сообщения вместе с комментарием и автором из последних комментариев с помощью get_comments.
$args = array( 'status' => 'approve', 'number' => 6, 'order' => 'DESC' ); $comments = get_comments($args); foreach($comments as $comment) : $count++; $post_args = array( 'post_type' => 'post', 'p' => $comment->comment_post_ID, 'posts_per_page' => 1 ); $posts = get_posts($post_args); foreach($posts as $post) : setup_postdata($post); the_title(); the_excerpt(); endforeach; echo $comment->comment_content; echo $comment->comment_author; endforeach;
В качестве дополнения к ответу Хао Лиана, если вы используете следующий запрос:
select wp_posts.*, coalesce( ( select max(comment_date) from $wpdb->comments wpc where wpc.comment_post_id = wp_posts.id ), wp_posts.post_date ) as mcomment_date from $wpdb->posts wp_posts order by mcomment_date desc limit 10
Это смешивается в сообщениях, которые еще не имеют комментариев, и сортирует их по post_date и max (comment_date).
Это старый вопрос, но у меня была такая же проблема, и я нашел гораздо более чистый способ сделать это, поэтому я размещаю его здесь, если это кому-то поможет.
Если вы используете фильтр posts_clauses, вы можете просто изменить основной запрос и по-прежнему использовать The Loop и все обычные функции цикла.
function intercept_query_clauses( $pieces ) { global $wpdb; $pieces['fields'] = "wp_posts.*, ( select max(comment_date) from " . $wpdb->comments ." wpc where wpc.comment_post_id = wp_posts.id AND wpc.comment_approved = 1 ) as mcomment_date"; $pieces['orderby'] = "mcomment_date desc"; return $pieces; } add_filter( 'posts_clauses', 'intercept_query_clauses', 20, 1 );
Обратите внимание, что я немного изменил sql для своих целей, но общая концепция такая же.
Код, предложенный Хао Лианом, отлично работает, за исключением того факта, что мы должны добавить следующее предложение WHERE, чтобы не вытягивать POST с comment_count = 0
, эта ситуация вызвана комментариями спама.
Предложение WHERE для добавления выглядит следующим образом:
WHERE comment_approved = '1' AND comment_type = '' AND post_password = ''
Полный код после добавления предложения where shoud выглядит следующим образом:
select wp_posts.*, max(comment_date) as comment_date from wp_posts right join wp_comments on id = comment_post_id WHERE comment_approved = '1' AND comment_type = '' AND post_password = '' group by ID order by comment_date desc limit 6
Я думаю, что добавление функции max приведет к потере ваших результатов. MySQL не собирается вытаскивать максимум из каждого. Он вытащит максимум из полного набора. Это запрос, который даст вам ваши результаты:
select wp_posts.*, comment_date from $wpdb->posts wp_posts right join $wpdb->comments on id = comment_post_id group by ID order by comment_date desc limit 10
После этого, если вы хотите следовать соглашению WP, используйте это, а затем вы можете использовать функции, которые используют большинство ваших шаблонов (на основе цикла):
$results = $wpdb->get_results($query) or die('!'); foreach ($results as $post): setup_postdata($post);
Получите 3 новых комментария для персонализированного типа «вопрос» независимо от одобрения:
global $wpdb; $results = $wpdb->get_results( " SELECT wp_posts.ID, MAX(comment_date) AS max_comment_date FROM wp_posts RIGHT JOIN wp_comments ON id = comment_post_id WHERE wp_posts.post_type = 'question' AND wp_posts.post_status = 'publish' GROUP BY ID ORDER BY max_comment_date DESC LIMIT 3 " ); foreach ($results as $result) { $posts_arr[] = $result->ID; } $args = array( 'post_type' => 'question', 'post__in' => $posts_arr, 'orderby' => 'post__in', ); $the_query = new WP_Query( $args );
Это можно сделать, объединив WP_Comment_Query с WP_Query, например:
// For performance, limit the number of queried comments, // but make it be something big enough to account for "duplicate" posts. $comments_query = new WP_Comment_Query; $comments = $comments_query->query( array( 'number' => '100' ) ); if ( $comments ) { foreach ( $comments as $comment ) { // You'll want to convert the dates from string to integer so you can sort them out later $comment_utf = strtotime($comment->comment_date); // Build an array of post IDs with the date of the last published comment $latest_comments[$comment->comment_post_ID] = $comment_utf; }} // Sort the array by date arsort($latest_comments); foreach ($latest_comments as $key => $value) { $posts_ordered[] = $key; } // The nice thing is that WP_Query will remove duplicates by default $args = array ( 'posts_per_page' => '10', 'post__in' => $posts_ordered, 'orderby' => 'post__in'); $query = new WP_Query( $args ); if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); // Do your stuff (add the template or whatever) // If you want to add the comment itself, use this: $comments = get_comments(array('number' => '1', 'post_id' => $post->ID)); foreach($comments as $comment) : echo $comment->comment_content; endforeach; // That's about it }} wp_reset_postdata();