WordPress 自定义查询 – 使用 WP_Query 类

已发表: 2021-02-06

WordPress 提供了广泛的即用型功能,在大多数情况下可以从数据库中检索必要的信息。 但是在开发 WordPress 网站时,有很多情况下过滤器或操作不足以达到预期的结果。 在这些情况下。 WordPress 以WP_Query类的形式提供了一种解决方法。

让我们看看如何使用WP_Query类!

自定义查询案例

注意:本文假设您对 PHP 和 MySQL/MariaDB 有一定的了解,并且熟悉使用 WordPress。

无论您访问什么页面,WordPress 都会运行所谓的“主查询”来显示内容。 因此,当您访问例如类别视图之类的页面时,会在后台创建一个WP_Query对象,并从数据库中检索所有必要的数据以显示该页面。

WP_Query的基本作用是让您能够从网站的数据库中检索内容,而无需使用 SQL 查询。

为此,我们需要做的就是定义与我们的需求相对应的参数,然后将创建一个新的WP_Query对象并将其转换为 SQL 查询。

使用 WP_Query 的示例

如果我们想在另一个类别模板中显示来自特定类别的帖子,则需要创建一个新的查询对象。

出于本示例的目的,我们激活了二十二十个主题,并在名为“类别 1”的类别下创建了 2 个帖子,并在名为“服务”的类别下创建了 2 个帖子。

此外,我们为“类别 1”帖子创建了一个自定义类别视图模板。 这个类别的 slug 是 'category-1' 因此主题文件夹下的文件应该是category-CATEGORYSLUG.php ,在我们的例子中是category-category-1.php

请将以下内容粘贴到category-category-1.php文件中。

 <?php /*** Custom Category 1 Template */ get_header(); ?> <main role="main"> <section class="site-content"> <div role="main"> <?php if ( have_posts() ) : ?> <header class="archive-header"> <h3 class="archive-title">Category: <?php single_cat_title( '', true ); ?></h3> </header> <?php while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; endif; ?> </div> </section> </main> <?php get_sidebar(); ?> <?php get_footer(); ?>

在循环之前,我们使用have_posts方法来确定循环中是否有更多可用的帖子。

the_post()是循环迭代帖子并告诉 WordPress 移动到帖子数组的下一个帖子所必需的。

此时,我们的类别 ( https://mycompanyname.com/category/category-1/ ) 的前端视图将如下所示:

我知道通过使用这段代码,我们忽略了包含很多帖子信息,但是为了这个示例,最好保持简单并且只显示帖子标题。

要查看 WordPress 为此视图创建的查询对象属性,我们只需在代码中的endif; 陈述。

 var_dump ( $wp_query->query_vars );

现在,如果您刷新页面,您将在帖子列表下看到此信息:

 array(63) { ["category_name"]=> string(10) "category-1" ["error"]=> string(0) "" ["m"]=> string(0) "" ["p"]=> int(0) ["post_parent"]=> string(0) "" ["subpost"]=> string(0) "" ["subpost_id"]=> string(0) "" ["attachment"]=> string(0) "" ["attachment_id"]=> int(0) ["name"]=> string(0) "" ["pagename"]=> string(0) "" ["page_id"]=> int(0) ["second"]=> string(0) "" ["minute"]=> string(0) "" ["hour"]=> string(0) "" ["day"]=> int(0) ["monthnum"]=> int(0) ["year"]=> int(0) ["w"]=> int(0) ["tag"]=> string(0) "" ["cat"]=> int(16) ["tag_id"]=> string(0) "" ["author"]=> string(0) "" ["author_name"]=> string(0) "" ["feed"]=> string(0) "" ["tb"]=> string(0) "" ["paged"]=> int(0) ["meta_key"]=> string(0) "" ["meta_value"]=> string(0) "" ["preview"]=> string(0) "" ["s"]=> string(0) "" ["sentence"]=> string(0) "" ["title"]=> string(0) "" ["fields"]=> string(0) "" ["menu_order"]=> string(0) "" ["embed"]=> string(0) "" ["category__in"]=> array(0) { } ["category__not_in"]=> array(0) { } ["category__and"]=> array(0) { } ["post__in"]=> array(0) { } ["post__not_in"]=> array(0) { } ["post_name__in"]=> array(0) { } ["tag__in"]=> array(0) { } ["tag__not_in"]=> array(0) { } ["tag__and"]=> array(0) { } ["tag_slug__in"]=> array(0) { } ["tag_slug__and"]=> array(0) { } ["post_parent__in"]=> array(0) { } ["post_parent__not_in"]=> array(0) { } ["author__in"]=> array(0) { } ["author__not_in"]=> array(0) { } ["ignore_sticky_posts"]=> bool(false) ["suppress_filters"]=> bool(false) ["cache_results"]=> bool(true) ["update_post_term_cache"]=> bool(true) ["lazy_load_term_meta"]=> bool(true) ["update_post_meta_cache"]=> bool(true) ["post_type"]=> string(0) "" ["posts_per_page"]=> int(10) ["nopaging"]=> bool(false) ["comments_per_page"]=> string(2) "50" ["no_found_rows"]=> bool(false) ["order"]=> string(4) "DESC" }

假设我们要在上面描述的帖子下显示属于“服务”类别的帖子列表。 由于页面已经为当前类别创建了一个查询对象,我们必须通过操作现有的主要查询参数来解决这个问题。

让我们看一下 WordPress 允许我们实现这一目标的方式。

query_posts 函数

query_posts()函数是一种更改 WordPress 用于显示帖子的主要查询的方法。 它通过将主查询放在一侧并用新查询替换它来做到这一点。 您可以在引入它的wp-includes/query.php文件中亲自看到这一点。

 function &query_posts($query) { unset($GLOBALS['wp_query']); $GLOBALS['wp_query'] =& new WP_Query(); return $GLOBALS['wp_query']->query($query); }

我们将尝试通过在endwhile; 当前标准循环。

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile;

你去吧:

然而,这种方法有一个缺点。 如果我们尝试打印查询对象中包含的类别,我们会注意到它已更改。

尝试插入var_dump ( $wp_query->query_vars["category_name"] ); 服务查询后刷新页面。 你应该看到这个结果:

 string(8) "services"

发生这种情况是因为查询已更改但从未恢复。 这种方法可能会导致我们查询后的内容出现很多问题。

为了避免这些冲突并在调用query_posts后进行清理,请调用wp_reset_query() ,原始主查询将被恢复。 所以你的代码应该是这样的:

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

刷新页面后,您现在会看到初始页面类别又回到了查询中。

 string(10) "category-1"

最后,我们应该提到应该避免query_posts ,因为它会增加查询的开销,因为它实际上会导致主查询再次运行。

get_posts() 函数

使用get_posts()函数检索与给定条件匹配的帖子数组可以实现相同的结果。

替换如下所示的服务循环...

 query_posts( array ( 'category_name' => 'services' ) ); while ( have_posts() ) : the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; wp_reset_query(); var_dump ( $wp_query->query_vars["category_name"] );

……有了这个:

 $my_query = get_posts( array ( 'category' => 17 ) ); foreach($my_query as $post) : setup_postdata($post); the_title( '<h4 class="example"></h4>' ); endforeach; var_dump ( $wp_query->query_vars["category_name"] );

正如您所看到的,这一次我们必须使用类别 ID 而不是类别名称,根据 WordPress 定义的get_posts()参数。

这里要注意的另一件重要的事情是,即使我们没有重置查询,查询类别的var_dump输出仍然完好无损,没有更改为“服务”。 这是因为get_posts()本身不会改变主查询。 我们只是使用了一个新变量“ $my_query ”来创建查询对象的一个​​新实例,而不用替换它。

get_posts()函数使用与query_posts()相同的参数,建议在您想在模板中的任何位置添加静态自定义循环时使用,因为它安全且易于使用。

创建一个新的 WP_Query 对象

$wp_queryWP_Query类的一个对象,用于检索当前页面所需的数据库内容。 覆盖这个类是我们自定义结果和显示不同内容的方式。

这是我们将使用的一段代码:

 $services_query = new WP_Query( 'category_name=services' ); if ( $services_query->have_posts() ) { while ( $services_query->have_posts() ) : $services_query->the_post(); the_title( '<h4 class="example"></h4>' ); endwhile; } wp_reset_postdata(); var_dump ( $wp_query->query_vars["category_name"] );

我们使用 'category_name' 参数来定义我们希望其帖子显示的类别的 slug。

我们保存了新对象new WP_Query( 'category_name=services' );$services_query变量中。

然后我们使用一个while循环来显示内容,然后我们用wp_reset_postdata();重置循环。 为了恢复到主查询的原始数据。

如果您想试验 WP_Query WordPress 类的其他参数,您可以在其 WordPress Codex 页面上找到完整列表。