WordPress主循环

3条评论

WordPress主循环

WordPress用主循环(The Loop)显示用户的文章。通过The Loop,WordPress可以将每篇文章显示在当前页面,并将这些文章按The Loop标签中的指定标准进行排版。The Loop中的任何HTML或PHP代码重复出现在每篇文章上。若WordPress文档宣布“该标签必须出现在The Loop中”,于是指定的模板标签或插件就会重复出现在每篇文章中。

例如,WordPress 1.5中The Loop默认显示的信息包括:每篇文章的标题((the_title()),时间(the_time())以及类别(the_category())。关于文章的其它信息则由相应的模板标签或(仅供高级用户)通过访问$post变量显示,运行The Loop时已经在当前文章信息中设置了该变量。

The Loop基本知识参见运行中的The Loop(主循环)

使用The Loop

The Loop应该存储在index.php以及任何用以显示文章信息的模板中,存放位置取决于WordPress版本。所以请先“确定正在使用的WordPress版本”。

WordPress 1.5 - 2.7

在主题模板的顶端应该包含对页眉模板的调用。如果用户在自己的版块设计(设计的不是模板)中使用The Loop,需要将WP_USE_THEMES设为false。

<?php define('WP_USE_THEMES', false); get_header(); ?>

The Loop开始于:

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>  

结束于:

<?php endwhile; else: ?>  
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>  
<?php endif; ?>  

WordPress 1.2

在索引页面顶端应该包含对wp-blog-header.php的调用。记住,一定要将wp-blog-header.php的路径设为wp-blog-header.php文件存放的位置:

<?php /* Don't remove this line. */ require('./wp-blog-header.php'); ?>  

The Loop开始于:

<?php if ( $posts ) : foreach ( $posts as $post ) : start_wp(); ?>  

结束于:

<?php endforeach; else: ?>  
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>   
<?php endif; ?>  

Loop示例

为某一类别的文章作特别样式设计

仅供WordPress 1.5版本

本示例使用WordPress 1.5版的语句规则,显示文章的标题(标题将被用作文章的固定链接)、类别和内容。这是一个仅有框架的简单实例;通过用CSS进行样式设计,用户的模板中可以轻松显示更多信息。

为了更具有说明性,这个例子还为编号为3的类别中的文章做了特殊设计。需要用 in_category() 模板标签来完成这一设计。

<!-- -->标签是HTML评论标签;使用这个示例时这些标签都不会显示在web浏览器中。它们的存在目的就是解释以下代码。

 <!-- Start the Loop. -->
 <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

 <!-- The following tests if the current post is in category 3. -->
 <!-- If it is, the div box is given the CSS class "post-cat-three". -->
 <!-- Otherwise, the div box will be given the CSS class "post". -->
 <?php if ( in_category('3') ) { ?>
           <div class="post-cat-three">
 <?php } else { ?>
           <div class="post">
 <?php } ?>

 <!-- Display the Title as a link to the Post's permalink. -->
 <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>

 <!-- Display the Time. -->
 <small><?php the_time('F jS, Y'); ?></small>

 <!-- Display the Post's Content in a div box. -->
 <div class="entry">
   <?php the_content(); ?>
 </div>

 <!-- Display a comma separated list of the Post's Categories. -->
 <p class="postmetadata">Posted in <?php the_category(', '); ?></p>
 </div> <!-- closes the first div box -->

 <!-- Stop The Loop (but note the "else:" - see next line). -->
 <?php endwhile; else: ?>

 <!-- The very first "if" tested to see if there were any Posts to -->
 <!-- display.  This "else" part tells what do if there weren't any. -->
 <p>Sorry, no posts matched your criteria.</p>

 <!-- REALLY stop The Loop. -->
 <?php endif; ?>

注意:使用HTML代码时一定要在<?php  ?>标签外使用。PHP代码(即使是大括号)都必须放在 <?php  ?>标签内。即使在if和else语句中,用户也可以启动或停止PHP代码以点缀HTML代码。如上例所示。

删除某一分类的文章

供WordPress 1.5或更高版本

本示例可使特定分类不显示在页面上。基本用法基于上个示例。

 <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

 <!-- If the post is in the category we want to exclude, we simply pass to the next post. -->
 <?php if (in_category('3')) continue; ?>
 
 <div class="post">
 
  <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
 
  <small><?php the_time('F jS, Y'); ?></small>
 
  <div class="entry">
    <?php the_content(); ?>
  </div>

  <p class="postmetadata">Posted in <?php the_category(', '); ?></p>
 </div> <!-- closes the first div box -->

 <?php endwhile; else: ?>
 <p>Sorry, no posts matched your criteria.</p>
 <?php endif; ?>

注意:在主页中使用该示例时,需要为分类存档使用不同模板。否则仅仅在查看分类存档时,WordPress也会删除分类3中所有文章。

如果想使用同样的模板也可以通过 is_home()标签解决上述问题:

...  
<?php if (in_category('3') && is_home() ) continue; ?>  
...  

这样分类3中的文章就只会在主页上被删除。根据指定页面的特定条件是否为真,其他条件标签也可以控制输出结果。

请注意,即使文章不显示在主页上,但WordPress在统计所显示的文章总数时仍然将它计算在内——这就是说,如果设置在WordPress主页上显示7篇文章,其中2篇属于分类3,这样在主页上就只会显示5篇文章。在布局和设计FAQ上可以找到更详细的说明,如果只是希望在the loop中删除一个类别,也可以使用 query_posts

多循环

本段内容针对The Loop的高级用户,因此有一定技术难度——但也无需担心。文章会从简单的地方切入。只要有点常识,有点耐心,有点热情,同样可以操作多循环。

首先,“为什么要使用多循环?”总的来说,原因就是,用户可能希望对一组文章进行一种操作,对另一组文章进行另一种操作,但希望两组文章最终出现在同一网页中。这里的操作可以使任一种操作;只要PHP技术过硬,想象力够丰富,任何操作都不是难题。

分析下面的示例前需要了解一些基本循环的知识,基本循环由以下部分组成:

     <?php if (have_posts()) : ?>
               <?php while (have_posts()) : the_post(); ?>    
     <!-- do stuff ... -->
     <?php endwhile; ?>

将以上代码译成英文就是(了解PHP和代码语言的人可以忽略本段内容):如果要显示文章,请逐篇选择。根据<!-- do stuff ... -->显示列表中的文章。点击最后一篇文章时终止运行。do stuff命令行与模板相关。

Do suff旁:这是一个简单示例,代码段的占位符可决定如何在网页上显示文章并进行排版。根据用户对WordPress外观的希望,下列代码可以有所改变。查看Kubrick主题的index.php文件时,会发现do stuff区域显示如下:

<?php while (have_posts()) : the_post(); ?>  

对上述代码来说:

<?php comments_popup_link('No Comments »', '1 Comment »', '% Comments »'); ?>  

这里是编码人员的说明:have_posts()和the_post()都是围绕全局变量$wp_query对象的便捷包装器,在$wp_query对象中操作所有动作。在博客的页眉以及GET 和 PATH_INFO的变量中调用$wp_query。$wp_query获取这些变量,然后创建并执行数据库查询,从而返回文章数组。该数组被存放在对象中并返回到博客页眉,在页眉处数组被放入全局数组$posts(兼容原有文章loop)。

WordPress将博客页眉加载完毕后,会回到模板中,这样就完成了文章loop。have_posts()调用 $wp_query->have_posts(),后者检查循环计数器,确认是否有文章遗留在文章数组中。 the_post()调用$wp_query->the_post(),后者加速循环计数器并设置全局变量$post以及所有全局文章数据。循环负载过多会导致have_posts()返回false。

循环示例

以下是两个使用多循环的示例,使用关键在于$wp_query只能调用一次。调用rewind_posts()或创建一个新查询对象,可增加调用$wp_query的调用次数。示例1显示了这种用法。示例2则用变量来存储查询结果。示例3记录update_post_caches()的用法;避免产生常见插件问题。最后,“活动的多循环”中介绍了很多方法,多循环通过这些方法可以推广博客主页上特定类别的文章。

多循环示例1

调用rewind_posts()使相同查询进行再次循环。该动作将重置循环计数器,而后进行再次循环。

  <?php rewind_posts(); ?>
 
  <?php while (have_posts()) : the_post(); ?>
    <!-- Do stuff... -->
  <?php endwhile; ?>

完成初始查询中的文章后,可以使用另一个查询。通过调用query_posts()可循环使用$wp_query对象, 而后重复循环。query_posts将执行新查询,创建新文章数组并重置循环计数器。

  // Get the last 10 posts in the special_cat category.
  <?php query_posts('category_name=special_cat&showposts=10'); ?>

  <?php while (have_posts()) : the_post(); ?>
    <!-- Do special_cat stuff... -->
  <?php endwhile;?>

如果希望保持初始查询,可以创建新的查询对象。

<?php $my_query = new WP_Query('category_name=special_cat&showposts=10'); ?>

<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
  <!-- Do special_cat stuff... -->
<?php endwhile; ?>

全局变量 have_posts() and the_post()都使用$wp_query,因此这里不使用这两个全局变量而使用查询对象my_query,然后调用新$my_query对象。

多循环示例2

另一种多循环使用方法解决了have_posts() and the_post()不能使用的情况。首先将初始查询存入变量,然后用另一个循环为变量重新赋值。完成以上操作后就可以使用所有依靠变量的标准函数了。

例如:

// going off on my own here
<?php $temp_query = $wp_query; ?>
<!-- Do stuff... -->

<?php query_posts('category_name=special_cat&showposts=10'); ?>

<?php while (have_posts()) : the_post(); ?>
  <!-- Do special_cat stuff... -->
<?php endwhile; ?>

// now back to our regularly scheduled programming
<?php $wp_query = $temp_query; ?>

注意: PHP5中,引用对象时使用“=”操作符,而不像php4中使用复制的链接。用下列代码以使示例2能在PHP5 中运行:

 // going off on my own here
 <?php $temp_query = clone $wp_query; ?>
 <!-- Do stuff... -->
 
 <?php query_posts('category_name=special_cat&showposts=10'); ?>
 
 <?php while (have_posts()) : the_post(); ?>
   <!-- Do special_cat stuff... -->
 <?php endwhile; ?>
 
 // now back to our regularly scheduled programming
 <?php $wp_query = clone $temp_query; ?>

示例2在WordPress 2.1中无法运行。

多循环示例3——插件

事实证明,某些插件与多循环无法保持良好运行状态。人们发现在这样的情况下,那些处理关键字和文章标签的插件只能在页面的首例循环中运行,页面中的循环由所有文章的子集组成。如果上述情况属实,可以尝试执行基本循环,该循环添加了 update_post_caches($posts)函数。该函数重置文章缓存且未被记录。仅在页面的第一次循环检索到文章子集时,第二次循环可执行基本循环。

将:

   <?php if (have_posts()) : ?>
               <?php while (have_posts()) : the_post(); ?>    
     <!-- Do stuff... -->
   <?php endwhile; ?>

修改为:

   <?php if (have_posts()) : ?>
               <?php while (have_posts()) : the_post(); update_post_caches($posts); ?>
     <!-- Do stuff... -->
   <?php endwhile; ?>
活动的多循环

了解多循环用法的最佳方式是给出用法的实例。多循环的最普遍用法可能就是在一个页面上显示两个(或更多)文章列表。当网站管理员需要计算最新文章以及特定类别文章时,可使用多循环的这一用法。

若将格式和CSS问题忽略不计,假定需要两个文章列表。要求其中一列列出最新文章(最近添加的10篇标准文章),另一列中则只列出“featured”类别中的一篇文章。这样就首先显示出该类别中所有文章,而后显示第二列文章(标准文章)。难处在于,一篇文章不能同时在两个类别中显示

第一步,从“featured”类别中获取一篇文章。

  <?php $my_query = new WP_Query('category_name=featured&showposts=1');
  while ($my_query->have_posts()) : $my_query->the_post();
  $do_not_duplicate = $post->ID; ?>
    <!-- Do stuff... -->
  <?php endwhile; ?>

将以上代码译成英文:

将$wp_query值设置与“featured”类别中的所有文章的查询结果相等,然后得到一篇文章。将变量$do_not_duplicate的值设置为返回的的单篇文章编号。Do stuff命令行表示与检索到的文章相关的所有选项。

注意:下一步要用$do_not_duplicate的值来确定同一篇文章不同时出现在这两个列表中。

第二步,进行再次循环以获取最近X篇文章(X不为1)。

以下代码从X篇最新文章(X由WordPress首选项决定)中扣留已经在初始循环中显示的文章,然后根据Do stuff显示剩余文章:

  <?php if (have_posts()) : while (have_posts()) : the_post(); 
  if( $post->ID == $do_not_duplicate ) continue; update_post_caches($posts); ?>
   <!-- Do stuff... -->
  <?php endwhile; endif; ?>

将以上代码译成英文:

获取所有文章,如果有文章等于$do_not_duplicate,继续下一步操作,如果没有文章等于 $do_not_duplicate,则根据Do stuff显示所有文章。更新缓存以优化标签和关键字插件的运行。记住, $do_not_duplicate变量中包含已经显示的文章的编号。

最终结果

如果没有格式排版,代码最终显示结果如下:

  <?php $my_query = new WP_Query('category_name=featured&showposts=1');
  while ($my_query->have_posts()) : $my_query->the_post();
  $do_not_duplicate = $post->ID;?>
    <!-- Do stuff... -->
  <?php endwhile; ?>
    <!-- Do other stuff... -->
  <?php if (have_posts()) : while (have_posts()) : the_post(); 
  if( $post->ID == $do_not_duplicate ) continue; update_post_caches($posts); ?>
   <!-- Do stuff... -->
  <?php endwhile; endif; ?>

最终显示结果是一个具有两个列表的页面。第一个列表中仅有一篇文章——“feature”类别中的最新文章。第二个列表中包含X篇最新文章(X由WordPress首选项决定),这其中不包括第一个列表中所显示的文章。因此,如果“feature”类别中的原有文章被新文章取代,则原有文章被加入标准文章列表区(取决于用户设置的文章显示数量以及文章频率)。这一技术与模板层级联合生成不同外观的home.php和index.php。参见本页最下方的相关资源。

第一类别中多篇文章注意事项

若showposts大于等于2,这就需要稍微修改一下代码。变量$do_not_duplicate应被转换成一个数组,而非单个值。否则初始循环将终止,$do_not_duplicate值等于最新文章编号。最终导致再次循环中出现重复文章。要解决该问题,请将

<?php $my_query = new WP_Query('category_name=featured&showposts=1');
 while ($my_query->have_posts()) : $my_query->the_post();
 $do_not_duplicate = $post->ID;?>

替换为

<?php $my_query = new WP_Query('category_name=featured&showposts=2');
  while ($my_query->have_posts()) : $my_query->the_post();
  $do_not_duplicate[] = $post->ID ?>

注意,“showposts”可以设为任何数字。这将$do_not_duplicate 转换为数组。 然后将

<?php if (have_posts()) : while (have_posts()) : the_post(); if( $post->ID ==    
  $do_not_duplicate ) continue; update_post_caches($posts); ?>  

替换为

<?php if (have_posts()) : while (have_posts()) : the_post(); 
 if (in_array($post->ID, $do_not_duplicate)) continue;
 update_post_caches($posts); ?>

在这里用户可以保留showposts设置等值的样式(本例中值为2)。

文章来源

这篇关于多循环的文章整合了Ryan BorenAlex King Hackers Mailing List 上对循环的讨论以及MaxPower 上的教程。

更多The Loop相关资源

学习更多关于WordPress 主循环以及只在主循环内部运行的模板标签相关知识,请参阅:

外部资源:

#1
如何给最近一天的几篇文章特殊的样式呢
#2
可以在输出文章的时候,按日期条件把文章过滤出来 if(get_the_time('Y-m-d') == date('Y-m-d',time())){ echo "今天的文章"; } else echo "不是今天的文章"; 建议不要按日期提取,直接提取最新文章或热门文章比较好。
#3
我自定义了一个文章类型以及创建了分类,在单页面调用的时候为什么是一个文章列表的循环?而不是单篇文章的显示?