在"category.php"文件中,我需要以这种奇怪的方式排序我的帖子:
- 首先是作者不同于"admin"的所有帖子(按标题字母顺序排列)
- 比"admin"的所有帖子(按字母顺序排列)
下面是我用来执行查询的标准代码:
<?php global
$wp_query;
query_posts(
array_merge(
array('orderby' => 'title', 'order' => 'ASC'),
$wp_query->query
)
);
?>
关于如何完成它没有嵌套两个查询的想法吗?
提前感谢!
EDIT:以下是一些尝试过的代码,正如Sepster在他的回答的前一个版本中建议的那样。但在这一刻,这段代码开始显示所有的帖子从'admin'(而不是其他),直到文章的作者不同于'admin'来。此时,它将中断结果并跳转到下一页的结果。
<?php
global $wp_query;
query_posts(
array_merge(
array('orderby' => 'title', 'order' => 'ASC'),
$wp_query->query
)
);
$adminPosts = false;
for ($i=1; $i<=2; $i++) {
while ( $wp_query->have_posts() ) {
$wp_query->the_post();
$author = get_the_author();
if ($author == 'admin' && $adminPosts == false) break;
if ($author != 'admin' && $adminPosts == true) break;
// ALL MY STUFF
} // end while
rewind_posts();
$adminPosts=true;
} // end FOR
?>
更新:
我终于想出了一个可行的解决方案,但公平地说,这真的是一个学术练习;是的,它不需要执行第二个循环,但实际上,它相当复杂。
解决方案是,总之
-
开发一个自定义SQL语句,将按照所需的顺序返回行。
这是因为在SQL中,按照需要的顺序获得结果的唯一方法是对两个子集进行UNION。据我所知,使用"正常"WP查询操作是无法做到这一点的。
-
执行此查询,并遍历其结果,而不是标准的"the loop"
这是因为我们返回的是一个记录集,而不是一个
WP_Query
对象。 -
设置"Blog pages show at most X posts"设置为1
(在/wp-admin/options-reading.php)
一个常见的抱怨是在使用自定义查询时分页中断(顺便说一下,您正在使用的
query_posts()
方法容易受到此问题的影响)。关于如何正确地执行此操作有许多教程,例如:
- https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination
- https://codex.wordpress.org/Pagination Troubleshooting_Broken_Pagination
第一个建议实现"偏移和手动分页"。
我发现与自定义SQL语句相结合的最接近的实现是https://wordpress.stackexchange.com/a/28717。我从这个答案中借用了很多(所以我建议你去给它投票!)。
然而,这种技术(在其他更"标准"的自定义查询方法中)有一个已知的行为,即WP在最终页面上产生404(如果我理解正确的话,因为WP仍然使用自己的查询和相关的max-page=posts-per-page/posts计算来映射URL中的页码和交付的内容)。
请参阅http://wordpress.org/support/topic/explanation-and-workaround-for-error-404-on-category-pagination?replies=14了解有关此问题的详细信息,以及建议的解决方案(不幸的是,它不适用于我们的自定义SQL方法)。这个问题的一个已知的"解决方法"是将每页的帖子数量减少到1,例如http://wordpress.org/support/topic/custom-post-type-pagination-404-on-last-page
因此,假设您对每个页面1个帖子的全局设置感到满意(请记住,您需要在自定义查询中手动覆盖此设置),下面是代码:
:显然也
...
function get_users_posts_last($userDisplayName = 'Admin', $categoryName = '') {
global $wpdb, $paged, $max_num_pages;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$post_per_page = 5;
$offset = ($paged - 1)*$post_per_page;
$sql = "
SELECT SQL_CALC_FOUND_ROWS q.* FROM
(
(
SELECT
p.*
FROM
{$wpdb->posts} p
INNER JOIN {$wpdb->users} u ON p.post_author = u.ID
LEFT JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN {$wpdb->terms} t ON tt.term_id = t.term_id
WHERE
tt.taxonomy = 'category'
AND p.post_status = 'publish'
AND p.post_type = 'post'
AND u.display_name != '{$userDisplayName}'
" . ( $categoryName != '' ? "AND t.name = '{$categoryName}'" : "" ) . "
ORDER BY
p.post_title ASC
)
UNION
(
SELECT
p.*
FROM
{$wpdb->posts} p
INNER JOIN {$wpdb->users} u ON p.post_author = u.ID
LEFT JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN {$wpdb->terms} t ON tt.term_id = t.term_id
WHERE
tt.taxonomy = 'category'
AND p.post_status = 'publish'
AND p.post_type = 'post'
AND u.display_name = '{$userDisplayName}'
" . ( $categoryName != '' ? "AND t.name = '{$categoryName}'" : "" ) . "
ORDER BY
p.post_title ASC
)
) q
LIMIT {$offset}, {$post_per_page};
";
$sql_result = $wpdb->get_results( $sql, OBJECT);
$sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
$max_num_pages = ceil($sql_posts_total / $post_per_page);
return $sql_result;
}
...
category.php:
...
$postList = get_users_posts_last('admin'); // Note you can also pass a category name if necessary
if($postList) {
global $post;
foreach( $postList as $key=>$post ) {
setup_postdata($post);
// Render the post here
?>
<header class='entry-header'><h1 class='entry-title'><?php the_title(); ?></h1></header>
<div class='entry-content'><?php the_content(); ?></div>
<?php
}
// Render pagination here
?>
<div class="navigation">
<div class="previous panel"><?php previous_posts_link('« Previous page',$max_num_pages) ?></div>
<div class="next panel"><?php next_posts_link('Next page »',$max_num_pages) ?></div>
</div>
<?php
}
...
或者,只设置两个单独的查询;-)