缩略图
程序开发 \ WordPress \

wordpress循环之查询篇

如果说循环是wordpress模板系统的核心,那么查询就是循环的基础。没有查询得到的结果,循环就毫无意义,应该说循环根本就不会开始。但是查询出的结果又需要通过循环来把结果按照我们设计的格式显示出来。这就是两者之间的关系,今天就和大家介绍几种查询的方法。

默认查询

这种查询是自动发生的,几乎发生在我们的每次请求当中:当我们点击网站主页的时候、当我们点击某个分类的时候、当我们点击某个标签的时候……默认的查询就已经开始执行,我们只需要实现循环,就可以把结果显示出来。

这个默认的查询保存在一个全局变量$wp_query之中,查询的文章结果保存在全局变量$posts之中(也可以说保存在$wp_query->posts中)。当我们执行循环的时候,当前文章保存在全局变量$post当中。你可以想一想,像the_title、the_content这样的函数,并没有传递参数,为什么还可以显示不同的文章?其实它们显示的就是$post中保存各个值,如果我们改变了$post,the_content显示的内容也会改变。所以,除非你很明确你要做的事情,不然不要随便改变$posts、$post。

query_posts查询

当我们不满意默认查询的结果,或者说想更改默认查询的时候,query_posts函数就派上了用场。query_posts的作用就是按照我特有的条件,更改默认的查询以返回我们想要的结果。下面举个简单的例子。

经常会碰到这样一种情况,我们不想在首页显示某个分类(或某几个分类)下的文章。可能我们首先想到的方法就是在循环中加上一个判断,如果判断是该分类下的文章就不显示。不错,这个方法是可行的,但是会有一个问题:假设你在后台设置了每页显示10篇文章,首页上有两篇你想过滤掉的分类文章。如果在循环中过滤的话,最终首页只会显示8篇文章,而不是10篇。

而用query_posts可以完美的解决这种问题,假设某个分类的ID为22,下面我们来看一下query_posts是如何从首页中排除该分类下的文章的。

在开始循环之前,加入以下代码

$r = array('category__not_in'=>array(22));
$r = wp_parse_args( $query_string, $r ); //$query_string是默认的查询字符串,如果没有这一句,分页将会失效
  query_posts($r);

这样查询结果中就不包含分类ID为22的文章,如果还有其它分类不想显示(比如分类ID为23),只需要加入到category__not_in数组中即可,分类ID之间用逗号分开。以下给出完整的代码

<?php
$r = array('category__not_in'=>array(22,23));
$r = wp_parse_args( $query_string, $r );
query_posts($r);
if(have_posts()) :
     while(have_posts()) : the_post();
?>
      <p>在这里加入你的处理代码,比如显示文章标题</p>
      <p><?php the_title(); ?></p>
     <?php endwhile; ?>
<?php endif; ?>

从代码中我们也可以看到,这种查询支持have_posts和the_posts函数,因为query_posts查询改变了默认的查询$wp_query。那么,如果我们再想利用默认查询怎么办呢?很简单,在上面的循环结束之后,调用wp_reset_query即可

<?php wp_reset_query(); ?>

get_posts查询

get_posts只返回查询结果中的posts,不会改变默认的查询,即不会修改$wp_query。也正是因为没有修改$wp_query,因此循环中不能使用hvae_posts和the_post函数。

使用get_posts查询,一般都是使用foreach循环。我们看一下上面的例子使用get_posts查询的实现方法

<?php
$r = array('category__not_in'=>array(22,23));
$r = wp_parse_args( $query_string, $r );
$ps = get_posts($r);
foreach($ps as $p) : ?>
 <p>在这里加入你的处理代码,比如显示文章标题</p>
 <p><?php echo get_the_title($p->ID); ?></p>
<?php endforeach; ?>

这种方法的好处是比较独立,和默认的查询没有任何联系,但是不能调用the_title和the_content等这些模板函数。这里需要注意的是,get_posts的返回值千万不可传递给$posts,即不能这样写

$posts = get_posts($r);

因为这样会更改默认查询的posts值,从而引起混乱。如果你还想向以前那样直接使用the_title()和the_content()等模板函数的话,也不是不行,我前面也说过,你只需要修改$post这个值即可,即把foreach($ps as $p)改为foreach($ps as $post),完整代码如下

<?php
$r = array('category__not_in'=>array(22,23));
$r = wp_parse_args( $query_string, $r );
$ps = get_posts($r);
foreach($ps as $post) : ?>
 <p>在这里加入你的处理代码,比如显示文章标题</p>
 <p><?php the_title(); ?></p>
<?php endforeach; ?>

不过需要注意一点,当循环结束之后,$post的值已经不是默认的值,因此在循环之后调用的所有和$post有关的函数,都会显示循环的最后一篇文章的结果,比如评论的个数会显示上次循环的最后一篇文章的评论个数。把$post恢复默认值的方法和上面的一样,在循环结束之后调用一下

<?php wp_reset_query(); ?>

即可。

总结一下

这三种查询应该是最常用的查询,还有一种更底层的查询,就是直接使用WP_Query类,其实效果和get_posts类似,在这里就不做解释了,有兴趣的可以发邮件给我一起讨论。在使用这些查询的过程中,要时刻注意不要轻易使用$wp_query、$posts、$post这些变量,除非你非常清楚它们的作用。(当然,还有一种最最底层的查询,直接通过sql语句查询。)

附查询常用参数说明

以下是可以直接通过字符串传递的参数

  • showposts或posts_per_page —— 显示文章的数量(每页显示的数量),比如’showposts=10′
  • nopaging —— 不分页(即显示所有文章),比如’nopaging=1′
  • m —— 日期和时间, 比如m=’20091231′
  • year —— 年份,比如’year=2009′
  • monthnum —— 月份,比如’monthnum=12′
  • day —— 日期,比如’day=31′
  • p —— 文章ID,比如’p=192′
  • cat —— 指定分类ID,多个id之间用逗号隔开。比如’cat=1,2,3′即查询分类ID为1,2,3下的文章;而’cat=-1,-2,-3′则表示查询不在分类ID为1,2,3的文章。
  • tag —— 指定标签名,多个标签名之间用逗号隔开,比如’tag=domety,wordpress’
  • orderby —— 排序,可以取值:’author’, ‘date’, ‘title’, ‘modified’, ‘menu_order’, ‘parent’, ‘ID’, ‘rand’, ‘comment_count’

以下是需要通过数组传递的参数(以$r为例)

  • post__in —— 查找指定的文章ID,比如$r['post__in'] = array(1,2,3,4,5);
  • post__not_int —— 需要排除的文章ID,比如$r['post__not_in'] = array(1,2,3,4,5);
  • cat__in —— 包含指定的分类ID,比如$r['cat__in'] = array(1,2,3);
  • cat__not_in —— 排除指定的分类ID,比如$r['cat__not_in'] = array(1,2,3);
  • tag__in —— 包含指定的标签ID
  • tag__not_in —— 排除指定的标签ID

另外还有一些可以使用的参数,不过我还没有测试,等我测试以后再添加进来。

在本文的示例中使用的是数组传递参数的方式,也可以使用字符串传递的方式,比如

query_posts($query_string.'&cat=22,23');

注意多个参数之间使用&符号隔开。

添加评论

5 条评论

  1. 1 F

    vsweb

    2010-01-01 星期五 10:03

    高手啊 2010年啦 祝福你更高!

    回复
    • DDBug

      2010-01-01 星期五 12:20

      高手不敢当。2010年,又是一个新的起点,大家一起努力吧

      回复
  2. 2 F

    五笔字根查询

    2010-05-06 星期四 13:58

    很好的教程!!

    回复
  3. 3 F

    freemmorpg

    2010-10-10 星期天 09:54

    你好 加我QQ吧 119-276-959

    回复
  4. 4 F

    秦天SEO

    2011-09-27 星期二 18:37

    不知道如何使显示的总的文章数中不包含指定分类目录中的

    回复

添加评论