自立但不自私,自强但不自傲,自尊但不自高,自爱但不自娇,自珍但不自赏!

WordPress 文章查询调用的四种方式

技术文档 8726浏览 0评论

在 WordPress 中不论是在首页, 单篇文章, 单个页面, 分类文章, 标签文章, 最新文章, 相关文章, 随机文章, 热门文章... 都是需要先经过查询, 将文章筛选出来, 然后经过 Html 语句, 将最终结果显示在网页上.

WordPress 对文章的查询大概就是这四种方式: get_results(), get_posts(), WP_Query() 和 query_posts().

以下我以 '热评文章' 和 '相关文章' 作例子, 分析它们的不同点. (以下所有的代码都是可正确执行的)

第一种方式: get_results()

这是 WordPress 最原始的做法, 采用 SQL 语句对数据库直接查询, 速度最快, 但也是最不安全.

对一般人而言, 编写 SQL 查询语句容易出错, 后续的修改也不容易.

但绝佳的执行速度和能够发挥 SQL 所有全功能是它的最大优势.

使用中要注意的是, 为了避免影响 $post 循环, 变量名要用 $mypost 或其它没被使用过的名称.

<div>
<h3>Most Popular (test1)</h3>
<ul>
<?php
$post_num = 5; // 数量设定.
$exclude_id = $post->ID;
$myposts = $wpdb->get_results("
SELECT ID, post_title FROM $wpdb->posts
WHERE ID != $exclude_id
AND post_status = 'publish'
AND post_type = 'post'
ORDER BY comment_count
DESC LIMIT $post_num
"); // get_results() since 0.71 /wp-includes/wp-db.php
foreach($myposts as $mypost) {
echo '<li>&#9829; <a href="', get_permalink($mypost->ID), '">', $mypost->post_title, '</a></li>';
$exclude_id .= ' AND ID != ' . $mypost->ID; // 记录文章 ID, 让 Related Posts 不重复.(单独使用可删此行)
} // 注意上一行是用 ' AND ID != ' 是给下一个 get_results() 用, 如果改用其它方法要改为 ','
?>
</ul>
</div>
<?php
// Related Posts 写出来一大串代码, 我已放弃.
?>

第二种方式: get_posts()

get_posts() 是针对 get_results() 改善的, 它可用简单的参数来进行 get_results() 的动作, 类似一个界面, 让你比较容易和 SQL 沟通.

相对的, 语法虽然简单了, 多了中介是多耗了一点时间, 除此之外, 这个函数和以下两个函数都只能运行 SQL 部份的常用功能而已.

使用这个函数要注意, 执行前要将 $post 暂存, 执行完后再回复, 以免搞乱 $post 顺序, 这是后来针对此 bug 所作补丁.

<div>
<h3>Most Popular (test2)</h3>
<ul>
<?php
$post_num = 5; // 数量设定.
$tmp_post = $post;
$exclude_id = $post->ID;
$myposts =get_posts('numberposts='.$post_num.'&exclude='.$exclude_id.'&orderby=comment_count');
// get_posts() since 1.2.0 /wp-includes/post.php
foreach($myposts as $post) {
setup_postdata($post);
?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
$exclude_id .= ',' . $post->ID; // 记录文章 ID, 让 Related Posts 不重复.(单独使用可删此行)
}
$post = $tmp_post; setup_postdata($post);
?>
</ul>
</div>
<div>
<h3>Related Posts</h3>
<ul>
<?php
$post_num = 5; // 数量设定.
//$tmp_post = $post; // 单独使用要开此两行
//$exclude_id = $post->ID;
$tags = ''; $i = 0; // 先取 tags 文章.
$posttags = get_the_tags();
if ( $posttags ) {
foreach ( $posttags as $tag ) $tags .= $tag->name . ',';
$tags = strtr(rtrim($tags, ','), ' ', '-');
$myposts = get_posts('numberposts='.$post_num.'&tag='.$tags.'&exclude='.$exclude_id);
foreach($myposts as $post) {
?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
$exclude_id .= ',' . $post->ID; $i ++;
}
$post = $tmp_post; setup_postdata($post);
}
if ( $i < $post_num ) { // 当 tags 文章数量不足, 再取 category 补足.
$cats = ''; $post_num -= $i;
foreach ( get_the_category() as $cat ) $cats .= $cat->cat_ID . ',';
$cats = strtr(rtrim($cats, ','), ' ', '-');
$myposts = get_posts('numberposts='.$post_num.'&category='.$cats.'&exclude='.$exclude_id);
foreach($myposts as $post) {
?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
}
$post = $tmp_post; setup_postdata($post);
}
?>
</ul>
</div>

第三种方式: WP_Query()

因为 get_posts() 采用原来的 $post 循环, 执行之后 $post 顺序全乱了, 所以 WP_Query() 可以另开个副循环, 而不去干扰到 $post 主循环, 执行完后要用 wp_reset_query() 清除变量, 回到主循环.

因为用到更多内存, 速度会稍慢, 但很安全, 不会影响 $post 原有的相关变量或运算结果.

<div>
<h3>Most Popular (test3)</h3>
<ul>
<?php
$post_num = 5; // 数量设定
$exclude_id = $post->ID;
$args = array(
'post_password' => '', // test
'post_status' => 'publish', // 只选公开的文章.
'post__not_in' => array($exclude_id), // 排除当前文章.
'caller_get_posts' => 1, // 排除置顶文章.
'orderby' => 'comment_count', // 依评论数排序.
'posts_per_page' => $post_num
);
$query_posts = new WP_Query(); // WP_Query() since 1.5.0 /wp-includes/query.php
$query_posts->query($args);
while( $query_posts->have_posts() ) { $query_posts->the_post(); ?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
$exclude_id .= ',' . $post->ID; // 记录文章 ID, 让 Related Posts 不重复.(单独使用可删此行)
} wp_reset_query();
?>
</ul>
</div>
<div>
<h3>Related Posts</h3>
<ul>
<?php
$post_num = 5; // 数量设定.
//$exclude_id = $post->ID; // 单独使用要开此行
$posttags = get_the_tags(); $i = 0;
if ( $posttags ) { $tags = ''; foreach ( $posttags as $tag ) $tags .= $tag->name . ',';
$args = array(
'post_status' => 'publish',
'tag_slug__in' => explode(',', $tags), // 只选 tags 的文章.
'post__not_in' => explode(',', $exclude_id), // 排除已出现过的文章.
'caller_get_posts' => 1,
'orderby' => 'comment_date', // 依评论日期排序.
'posts_per_page' => $post_num
);
$query_posts = new WP_Query();
$query_posts->query($args);
while( $query_posts->have_posts() ) { $query_posts->the_post(); ?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
$exclude_id .= ',' . $post->ID; $i ++;
} wp_reset_query();
}
if ( $i < $post_num ) { // 当 tags 文章数量不足, 再取 category 补足.
$cats = ''; foreach ( get_the_category() as $cat ) $cats .= $cat->cat_ID . ',';
$args = array(
'category__in' => explode(',', $cats), // 只选 category 的文章.
'post__not_in' => explode(',', $exclude_id),
'caller_get_posts' => 1,
'orderby' => 'comment_date',
'posts_per_page' => $post_num - $i
);
$query_posts = new WP_Query();
$query_posts->query($args);
while( $query_posts->have_posts() ) { $query_posts->the_post(); ?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
} wp_reset_query();
}
?>
</ul>
</div>

第四种方式: query_posts()

这是最实用的, 连 WP 系统内部都常用的方法. 用的是 $post 主循环, 而没使用副循环, 所以设计时要多加考虑变量之间的相对关系, 以免发生难以预料的结果. 使用方法和写法与 WP_Query() 几乎完全相同 (这很方便在此两个函数之间随时转换). 然而我发现 query_posts() 速度比 WP_Query() 快了些, 仅次于 get_results(), 难怪 WP 系统常常用.

<div>
<h3>Most Popular (test4)</h3>
<ul>
<?php
$post_num = 5; // 数量设定
$exclude_id = $post->ID;
$args = array(
'post_password' => '', // test
'post_status' => 'publish', // 只选公开的文章.
'post__not_in' => array($exclude_id), // 排除当前文章.
'caller_get_posts' => 1, // 排除置顶文章.
'orderby' => 'comment_count', // 依评论数排序.
'posts_per_page' => $post_num
);
query_posts($args); // query_posts() since 2.0.0 /wp-includes/classes.php
while( have_posts() ) { the_post(); ?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
$exclude_id .= ',' . $post->ID; // 记录文章 ID, 让 Related Posts 不重复.(单独使用可删此行)
} wp_reset_query();
?>
</ul>
</div>
<div>
<h3>Related Posts</h3>
<ul>
<?php
$post_num = 5; // 数量设定.
//$exclude_id = $post->ID; // 单独使用要开此行
$posttags = get_the_tags(); $i = 0;
if ( $posttags ) { $tags = ''; foreach ( $posttags as $tag ) $tags .= $tag->name . ',';
$args = array(
'post_status' => 'publish',
'tag_slug__in' => explode(',', $tags), // 只选 tags 的文章.
'post__not_in' => explode(',', $exclude_id), // 排除已出现过的文章.
'caller_get_posts' => 1,
'orderby' => 'comment_date', // 依评论日期排序.
'posts_per_page' => $post_num
);
query_posts($args);
while( have_posts() ) { the_post(); ?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
$exclude_id .= ',' . $post->ID; $i ++;
} wp_reset_query();
}
if ( $i < $post_num ) { // 当 tags 文章数量不足, 再取 category 补足.
$cats = ''; foreach ( get_the_category() as $cat ) $cats .= $cat->cat_ID . ',';
$args = array(
'category__in' => explode(',', $cats), // 只选 category 的文章.
'post__not_in' => explode(',', $exclude_id),
'caller_get_posts' => 1,
'orderby' => 'comment_date',
'posts_per_page' => $post_num - $i
);
query_posts($args);
while( have_posts() ) { the_post(); ?>
<li>&#9829; <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
} wp_reset_query();
}
?>
</ul>
</div>

以上四种方式都有优缺点, 要选哪个用, 就看你自己挑了。

它们对数据库的查询次数都一样, 差别只是函数写法不同, 内存量不同, 运行耗时只有一点点差异。

如果只是小小一段简单代码, 用 get_results();

如果想用 get_results(), 但写不出来 SQL 语句, 就用 get_posts();

如果你写的是大程序, 程序明明写对, 但经常莫名其妙出错, 就用 WP_Query();

如果你写的是大程序, 头脑还很清醒, 知道错在哪里, 就用 query_posts();

如果你真有实力, 真有办法搞定 SQL, 就全部改用 get_results()。

转自:http://kan.willin.org/?p=1329

转载请注明:自由的风 » WordPress 文章查询调用的四种方式

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (7)

  1. 还是关注新浪微博比较好抢沙发~~~赞记述文

    Japhia2011-04-24 16:41 回复
  2. 在折腾的时候貌似第四种经常看到

    IM路人2011-04-26 15:37 回复