昨天介绍了为wordpress添加阅读RSS功能 的方法,使用的是wordpress自带的rss.php中集成的MagpieRSS类。经过今天一天对wordpress源代码的研究,又发现了一种方法,也是wordpress集成的功能,就是昨天提到了另一个比较流行的rss解析库SimplePie。目前wordpress自带的rss小工具以及后台管理面板显示的“wordpress开发日志”、“其它wordpress相关新闻”以及“最新插件”等,都是使用simplepie实现的,看来wordpress是放弃了MagpieRss,毕竟MagpieRSS已经几年没有更新了。

你可以在wp-includes\class-simplepie.php中找到SimplePie类的定义。SimplePie有自己的一套缓存机制,一种是数据库驱动,一种是文件驱动。不过wordpress对SimplePie的缓存机制进行了扩展,使用的是wordpress自身的数据库缓存机制(Transients)。我们先用wordpress默认的方法进行讲解。

fetch_feed函数

wordpress2.8之后增加了一个fetch_feed函数,可以直接通过url来解析RSS或者Atom,该函数的原型如下

 fetch_feed($url)

该函数根据指定的feed地址返回一个SimplePie对象,我们可以对返回的SimplePie对象进行遍历来获取我们想要的数据。以下是一个简单的例子

$feed = fetch_feed('http://domety.com/feed/');
$items = $feed->get_items(0,5);//显示最新的5篇文章
foreach($items as $item) {
 echo '标题: '.$item->get_title().'<br />'; //显示标题
 echo '原文地址: '.$item->get_link().'<br />';//显示文章链接
 echo '作者: '.$item->get_author().'<br />'; //显示作者信息
 echo '发布日期: '.$item->get_date().'<br />'; //显示发布日期
 echo '摘要: '.$item->get_description().'<br />'; //显示文章内容
}

上面说过,getch_feed返回的是一个SimplePie对象,因此上例的代码可以通过$feed来调用SimplePie的API函数

这种调用wordpress自带的fetch_feed函数有很多局限性,一是缓存的时间是12小时,在这12小时之内不会去更新feed列表;二是必须采用wordpress的数据库缓存机制,这种机制会频繁的对数据库进行查询和更新操作,用我的超级链接做的测试结果是:5个站点列表,进行数据库的查询次数在50+次,这个根据你订阅的站点数量有关。

改用SimplePie自身的文件缓存机制

SimplePie默认的缓存文件夹是根目录的cache文件夹,所以第一步是在网站的根目录下创建一个具有可写权限的cache文件夹。然后再调用相关函数之前,先包含wp-includes\class-feed.php(注意,不是class-simplepie.php)

require_once (ABSPATH . WPINC . '/class-feed.php');

接下来其实就是把fech_feed函数的实现发法复制过来,稍微修改一下,还是拿实例说话吧,请看代码:

require_once (ABSPATH . WPINC . '/class-feed.php');

$feed = new SimplePie();
$feed->set_feed_url('http://domety.com/feed/');//设置feed地址
$feed->set_file_class('WP_SimplePie_File'); //使用wordpress扩展的File类
$feed->set_cache_duration(7200); //设置缓存时间为2小时(7200秒)
$feed->init();
$feed->handle_content_type();

if ( $feed->error() )
     echo $feed->error();
else {
     $items = $feed->get_items(0,5);//显示最新的5篇文章
     foreach($items as $item) {
          echo '标题: '.$item->get_title().'<br />'; //显示标题
          echo '原文地址: '.$item->get_link().'<br />';//显示文章链接
          echo '作者: '.$item->get_author().'<br />'; //显示作者信息
          echo '发布日期: '.$item->get_date().'<br />'; //显示发布日期
          echo '摘要: '.$item->get_description().'<br />'; //显示文章内容
     }
}

其中$feed->set_file_class(‘WP_SimplePie_File’);这句我认为还是很重要的,这也是为什么包含class-feed.php的原因。WP_SimplePie_File是wordpress对SimplePie默认的文件处理类的扩展,做了不少改进。如果不加这句,可能会出现超时的错误。

$feed->set_cache_duration(7200);这句的作用是设置缓存过期时间(以秒为单位),默认是1个小时(3600秒)。如果你想用默认值的话,这一句可以删掉。当然,如果你想时时更新feed列表的话,可以把缓存过期时间设置的短一些,比如1分钟,不过这样比较占用服务器资源。大部分的博客一天也就更新几篇文章,所以没必要把缓存时间设置的那么短。

掌握以上技巧,基本上可以在你的网站自如的做RSS订阅了。为了加深理解,下面是一些扩展知识,可看可不看,但是看了对你是有好处的。

SimplePie的缓存机制

一、设置feed地址和缓存地址(默认在根目录的cache文件夹下)

二、SimplePie检查该feed是否已经缓存:

  1. 如果该feed已经缓存,并且没有过期的话,就使用缓存的feed
  2. 如果该feed没有缓存,SimplePie就抓取该feed并缓存下来
  3. 如果该feed已经缓存,但是已经过期(比如上例中已经超过设置的2个小时),SimplePie就使用HTTPCG技术向feed源发送请求,询问是否有更新:如果有更新,就使用新内容并重新缓存;如果没有更新就使用缓存的内容并重新设置缓存过期时间。

 

附“超级链接”源码

最后,为了进一步加深理解,附上我的“超级链接”源代码,以作参考

<?php
get_header();
require_once (ABSPATH . WPINC . '/class-feed.php');
$feed = new SimplePie();
?>

 <ul id="superlinks">
  <?php
  $bookmarks = get_bookmarks('category=53');
  foreach($bookmarks as $bookmark) {
   $rss = $bookmark->link_rss;
   $feed->set_feed_url($rss);
   $feed->set_file_class('WP_SimplePie_File');
   $feed->init();
   $feed->handle_content_type();
   if ( $feed->error() )
    continue;
   $item = $feed->get_item(0); ?>
  <li><div style="background:url(<?php echo $feed->get_favicon();//$rss.'favicon.ico'; ?>) no-repeat left center"><span><a href="<?php echo $bookmark->link_rss; ?>" title="订阅<?php echo $feed->get_title(); ?>" target="_blank">RSS</a></span><strong><a href="<?php echo $feed->get_permalink(); ?>" title="访问<?php echo $feed->get_title(); ?>" target="_blank"><?php echo $feed->get_title(); ?></a></strong><br /><small><?php echo $feed->get_description(); ?></small></div>最新文章: <a href="<?php echo $item->get_permalink(); ?>" title="阅读原文: <?php echo $item->get_title(); ?>" target="_blank"><?php echo $item->get_title(); ?></a></li>
  <?php } ?>
 </ul>
<div></div>
<?php
get_footer();
?>