现在我们已经了解了关于WP_Query 类的几乎所有内容,现在是时候尝试一些例子了。在这一部分,我们将在10个不同的场景中利用WP_Query 类和相关函数。
这将是一个有趣的练习,我希望它同样具有教育意义。让我们开始吧!
- 使用WP_Query创建一个循环的快速教程
- 例子1: 某作者今年的所有文章
- 例子2:这个类别的最新文章(除了当前的文章)
- 例子3: 按评论数排列的最受欢迎的文章
- 例子4: 一个简单的滑块设置
- 例子5:边栏的随机语录
- 例子6:在一个价格范围内列出产品
- 例子7: 一个嵌入帖子的短代码
- 例子8: 当前预定的帖子列表(可选摘录)
- 例子9:一年前的帖子,今天的帖子
- 例子10:显示当前页面的子女
- 关于WP_Query需要记住的要点
关于用WP_Query创建循环的快速教程
作为复习,这里有一个关于用WP_Query 类创建WordPress循环的小型教程。
这与创建一个普通的循环没有什么不同,真的。一个典型的WordPress循环是这样的。
<?php
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
// Post data goes here.
}
}
?>
而用WP_Query 类来创建一个循环,只有几个区别。
<?php
$args = array(
'category_name' => 'news',
'posts_per_page' => 3
);
$my_query = new WP_Query( $args );
if ( $my_query->have_posts() ) {
while ( $my_query->have_posts() ) {
$my_query->the_post();
// Post data goes here.
}
}
// Reset the `$post` data to the current post in main query.
wp_reset_postdata();
?>
让我们看看第二个例子中的区别。
- 我们为我们的
WP_Query实例设置了一些参数 - 我们实例化了
WP_Query类 - 我们在
have_posts()和the_post()函数的开头添加了$my_query->(所以它们现在是WP_Query类的方法)。 - 我们重置了
$post的数据,这样它就可以返回到主查询。
现在我们知道了如何用WP_Query 创建一个循环,以及普通循环和用WP_Query 创建的循环之间的区别。我们不会在每个例子中都创建循环(为了保持教程的简短和主题),所以如果你需要用下面的例子创建一个循环,你可以参考本节。
例子1:一个作者在这一年里的所有帖子
假设你想在一个特殊的 "今年作者的文章"部分列出一个特定作者在今年写的文章。两个WP_Query 参数的简单组合就足够了。
<?php
// Get the year we're in.
$current_year = date( 'Y' );
// Setup arguments.
$args = array(
// Get the author with the nicename "john".
'author' => 'john',
// Get his posts from this year.
'year' => $current_year
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
?>
在一个循环中传递这个查询,你就可以开始了!
例子 2: 这个类别的最新文章(除了当前的文章)
假设你想在每个帖子的单页下创建一个循环,并列出该帖子所在类别的最新帖子。当然,你必须排除当前的帖子,以防它可能是该类别的最新帖子之一。以下是你如何创建带有'cat' 和'post__not_in' 参数的查询。
<?php
// Get the current post id.
$current_post_id = get_the_ID();
// Get the current post's category (first one if there's more than one).
$current_post_cats = get_the_category();
$current_post_first_cat_id = $current_post_cats[ 0 ]->term_id;
// Setup arguments.
$args = array(
// Get category's posts.
'cat' => $current_post_first_cat_id,
// Exclude current post.
'post__not_in' => array( $current_post_id )
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
?>
对于循环,我建议在帖子标题上方创建三或四列的帖子缩略图。它将在帖子下面和评论区之前看起来非常漂亮。
例子3:按评论数排列的最受欢迎的帖子
WordPress没有一个内置的帖子浏览计数系统,而提供这种功能的插件以拖慢网站速度而闻名(因为在每一个帖子浏览时,插件都要在数据库中反复写,以记录浏览计数)。然而,还有一种测量方法可以确定哪些帖子最受欢迎:计算评论。与浏览次数不同,评论次数已经在数据库中了--WP_Query 类使得按评论次数排列帖子变得非常容易。
<?php
// Setup arguments.
$args = array(
// Order by comment count.
'orderby' => 'comment_count'
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
?>
看看这有多简单?现在想象一下,创建一个带有循环的自定义页面模板,运行这个查询--最多评论的帖子 页面。
例子4:一个简单的滑块设置
当使用WordPress建立企业网站、作品集或网络杂志时,滑块已经成为一个必须的工业标准。我不太喜欢滑块(我认为它的用户体验不好),但网络似乎喜欢它,所以我在为我的客户制作网站时不能对他们说不。如果他们想要滑块,我使用一个简单的查询,使用WP_Query 类。
<?php
// Setup arguments.
$args = array(
// Get the "slider" post type.
'post_type' => 'slider',
// Get a specific slider category.
'category_name' => 'home-slides',
// Get all slides and don't paginate.
'nopaging' => true
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
?>
'cat' 参数可以用来检索不同类别的幻灯片,这样你就可以把幻灯片组分开,在多个页面上使用多个滑块。如果你打算在你的网站中只使用一个滑块,你可以删除这一行,就可以了。
例子5:边栏里的随机语录
如果你热衷于文学或宗教,你可能想在侧边栏里放一些你最喜欢的名言--如果你有目的地使用这个区域,就不会浪费空间了。因此,如果你要在每个页面浏览时在侧边栏中随机列出一句话,你可以使用下面的代码片段来创建帖子类型,并使用下面的查询来在侧边栏中创建一个循环。
<?php
/*
* Create new post type called "Quotes"
* (refer to the `register_post_type` function to
* learn more about creating custom post types).
*/
function quote_post_type() {
$args = array(
'label' => 'Quotes',
'public' => true
);
register_post_type( 'quotes', $args );
}
add_action( 'init', 'quote_post_type' );
// Setup arguments.
$args = array(
// Get the "quotes" psot type.
'post_type' => 'quotes',
// Randomize the order.
'orderby' => 'rand',
// Get only one item.
'posts_per_page' => 1,
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
?>
一个简单而优雅的解决方案。
例子6:在一个价格范围内列出产品
我在Scribu.net上发现了这个例子,我必须说,它可能是本教程中最好的WP_Query 。它也比其他的更有技术性,因为在这种情况下,它可以应用于由WordPress驱动的电子商务网站。
如果你想从一个自定义的产品帖子类型中列出项目,并使用价格自定义字段过滤结果,你将使用以下代码片段。
<?php
// Source: https://scribu.net/wordpress/advanced-metadata-queries.html
// Setup arguments.
$args = array(
// Get the "product" post type.
'post_type' => 'product',
// Setup the "meta query".
'meta_query' => array(
array(
// Get the "price" custom field.
'key' => 'price',
// Set the price values.
'value' => array( 100, 200 ),
// Set the compare operator.
'compare' => 'BETWEEN',
// Only look at numeric fields.
'type' => 'numeric',
)
)
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
?>
衷心感谢Silviu-Cristian Burca!
例子 7: 嵌入帖子的短代码
这里有一个有趣的练习--我们也可以使用Shortcode API!在这个例子中,我们将创建一个短码,可以在一个帖子中嵌入一个帖子。[postception](在下面的代码中,我们创建了一个短码函数,允许我们嵌入帖子(或任何自定义帖子类型),并让我们选择是否显示完整的帖子或只是一个摘录。
<?php
/*
* Usage:
*
* [embed_post slug="my-post"]
* [embed_post slug="my-post" full="false"]
* [embed_post type="movie" slug="inception"]
*/
function tutsplus_embedded_post_shortcode( $attributes ) {
// Extract shortcode attributes.
extract(
shortcode_atts(
array(
'type' => 'post',
'slug' => '',
'full' => true
),
$attributes
)
);
// Setup arguments.
$args = array(
// Get post type ("post" by default).
'post_type' => $type,
// Get post by slug.
'name' => $slug
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
// Check that we have query results.
if ( $my_query->have_posts() ) {
// Begin generating markup.
$output = '<section class="embedded-post">';
// Start looping over the query results.
while ( $my_query->have_posts() ) {
$my_query->the_post();
// Add title to output.
$output .= '<h2 class="embedded-post-title">';
$output .= get_the_title();
$output .= '</h2>';
// Get full post if `$full` is true, otherwise, show the get excerpt
if ( 'true' === $full ) {
// Add full content to output.
$output .= '<div class="embedded-post-content">';
$output .= get_the_content();
$output .= '</div>';
} else {
// Add excerpt to output.
$output .= '<div class="embedded-post-excerpt">';
$output .= get_the_excerpt();
$output .= '… <a href="' . get_permalink() . '">' . __( 'See full post', 'tutsplus' ) . ' »</a>';
$output .= '</div>';
}
}
// End generating markup.
$output .= '</section>';
} else {
// Output message to let user know that no posts were found.
$output = '<section class="embedded-post-error">';
$output .= '<p>' . __( 'No posts found.', 'tutsplus' ) . '</p>';
$output .= '</section>';
}
wp_reset_postdata();
return $output;
}
add_shortcode( 'embed_post', 'tutsplus_embedded_post_shortcode' );
?>
例子 8: 当前预定的帖子列表(可选择摘录)
这里有一个想法。你为什么不向你的访问者展示一些即将发布的帖子的偷拍内容呢?你可以使用下面的功能来列出你预定的帖子,在标题后面加上或不加上摘录。
<?php
/*
* Usage with Excerpts:
* <?php echo tutsplus_show_drafts(); ?>
*
* Usage without Excerpts:
* <?php echo tutsplus_show_drafts( false ); ?>
*/
function tutsplus_show_drafts( $show_excerpts = true ) {
// Setup arguments.
$args = array(
'post_status' => 'future',
'nopaging' => true
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
// Check that we have query results.
if ( $my_query->have_posts() ) {
// Begin generating markup.
$output = '<section class="pending-posts">';
// Start looping over the query results.
while ( $my_query->have_posts() ) {
$my_query->the_post();
// Output draft post title and excerpt (if enabled).
$output .= '<div class="pending">';
$output .= '<h3 class="pending-title">' . get_the_title() . '</h3>';
$output .= get_the_title();
$output .= '</h3>';
if ( $show_excerpts ) {
$output .= '<div class="pending-excerpt">';
$output .= get_the_excerpt();
$output .= '</div>';
}
$output .= '</div>';
}
// End generating markup.
$output .= '</section>';
} else {
// Let user know that nothing was found.
$output = '<section class="drafts-error">';
$output .= '<p>' . __( 'Nothing found', 'tutsplus' ) . '</p>';
$output .= '</section>';
}
wp_reset_postdata();
return $output;
}
?>
例子9:一年前的文章今天发布
如果你的博客超过一年,而且你的内容是永恒的(意味着2015年和2025年的人都能找到相关的文章),添加一个 "一年前的今天"部分可能会提高你的页面浏览量。以下是你如何做的。
<?php
// Setup arguments.
$args = array(
// Day (1 - 31).
'day' => date( 'j' ),
// Month (1 - 12).
'monthnum' => date( 'n' ),
// Year (minus 1).
'year' => date( 'Y' ) - 1,
// Show only one post.
'posts_per_page' => 1
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
?>
使用这个查询来建立一个循环,显示过去的一篇文章。
例子 10: 显示当前页面的子页面
除了子页面的标题,你没有其他东西可以放在你的服务、我们的作品或我的作品集页面内?也许有一段介绍,但你是对的,这些页面注定是占位符。不过,把子页面放在里面也是一个好主意--也许是一个带有方形缩略图的网格,下面是标题。让我们看看在创建这样的页面模板时,我们应该使用哪些查询。
<?php
$current_page_id = get_the_ID();
// Setup arguments.
$args = array(
// Get children of current page.
'parent' => $current_page_id,
// Disable pagination.
'nopaging' => true
);
// Instantiate new query instance.
$my_query = new WP_Query( $args );
?>
关于WP_Query,需要记住的关键点
WP_Query 类在你的WordPress网站上循环浏览帖子数据时给你很大的权力。它有很多选项来帮助你缩小你想输出的帖子列表。然而,有几件事你应该牢记在心。
主查询与次要查询
在WordPress有两种类型的查询。第一种是当你访问一个网页时,WordPress通过分析你要访问的URL而自动运行的。这就是主查询。请记住,主查询不一定是被WordPress执行的第一个查询。除了WordPress根据请求的URL创建的查询外,所有其他类型的查询都是辅助查询。二级查询的例子是我们在前面的章节中创建的查询。
运行查询后重新设置数据
你应该在运行你的自定义或二级查询后,总是调用wp_reset_postdata() 函数。这个函数将恢复全局$post 变量的值,使其包含关于主帖的信息。换句话说,它基本上将模板标签的上下文从二级查询循环恢复到主查询循环。
还有一个类似于wp_reset_postdata() 的函数,叫做wp_reset_query() 。这两者之间的区别是,后者的函数将主查询重置为原始的主查询,然后调用wp_reset_postdata() 。
只有当你在代码中某处使用了query_posts() 函数时,你才需要调用wp_reset_query() 。然而,你应该避免在主题或插件中调用query_posts() 函数,因为这个函数会改变你的主查询。
改变主查询
如果你想对主查询进行修改怎么办?你应该通过使用pre_get_posts ,然后使用is_main_query() ,以确保你是在处理主查询。下面是一个例子。
<?php
function search_blacklist($query) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search()) {
$query->set( 'post__not_in', array( 218 ) );
}
}
add_action( 'pre_get_posts', 'search_blacklist' );
?>
这里我们使用pre_get_posts 钩子来执行一个函数,这个函数将阻止具有特定id的帖子出现在搜索结果中。你可以编写上述函数的变体,将搜索结果限制在一个特定的日期或类别等。
总结
我希望你和我在准备这些例子时一样喜欢它们。我特别注意给出不同的例子,既是为了好玩,也是为了激发你的创造力。
如果你在阅读这些例子时想到了更好的例子,或者有问题,不要犹豫,请在下面留言。如果你喜欢这篇文章,别忘了与你的朋友分享它
在下一部分中,我们将讨论WP_User_Query ,它是WP_Query 的姐妹类之一。届时见!