在WordPress中实现搜索结果按浏览量排序,需要结合浏览量统计功能。以下是几种实现方法,从简单到复杂:
方案一:使用插件组合(无需代码,最简单)
1. 安装必需插件
- WP-PostViews 或 Post Views Counter – 用于统计浏览量
- SearchWP 或 Relevanssi – 高级搜索插件(支持自定义排序)
2. 使用 Post Views Counter + Relevanssi(推荐组合)
- 安装并激活 Post Views Counter 和 Relevanssi
- 在 Relevanssi 设置中:
- 进入“设置” > “Relevanssi” > “搜索结果排序”
- 选择“自定义字段”作为主要排序
- 在字段中输入:
post_views(Post Views Counter 使用的字段名) - 选择“数字”和“降序”
方案二:纯代码实现(使用 WP-PostViews 插件的数据)
如果你已经在使用 WP-PostViews 插件,添加以下代码到主题的 functions.php:
/**
* 修改搜索结果查询,按浏览量排序
*/
function search_results_by_views( $query ) {
// 仅在前端搜索结果页面,且是主查询
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
// 获取排序参数
$orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : 'views';
if ( $orderby === 'views' ) {
$query->set( 'meta_key', 'views' ); // WP-PostViews 的字段名
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'order', 'DESC' );
}
}
}
add_action( 'pre_get_posts', 'search_results_by_views' );
/**
* 在搜索结果页面添加排序选项
*/
function add_search_sorting_options() {
if ( is_search() ) {
$current_order = isset( $_GET['orderby'] ) ? $_GET['orderby'] : 'relevance';
$search_query = get_search_query();
?>
<div class="search-sorting-options">
<span>排序方式:</span>
<a href="<?php echo esc_url( add_query_arg( array( 's' => $search_query, 'orderby' => 'relevance' ) ) ); ?>"
class="<?php echo $current_order === 'relevance' ? 'active' : ''; ?>">
相关度
</a>
<a href="<?php echo esc_url( add_query_arg( array( 's' => $search_query, 'orderby' => 'views' ) ) ); ?>"
class="<?php echo $current_order === 'views' ? 'active' : ''; ?>">
浏览量
</a>
<a href="<?php echo esc_url( add_query_arg( array( 's' => $search_query, 'orderby' => 'date' ) ) ); ?>"
class="<?php echo $current_order === 'date' ? 'active' : ''; ?>">
最新
</a>
</div>
<style>
.search-sorting-options {
margin: 20px 0;
padding: 15px;
background: #f5f5f5;
border-radius: 5px;
}
.search-sorting-options span {
font-weight: bold;
margin-right: 10px;
}
.search-sorting-options a {
margin: 0 10px;
padding: 5px 15px;
background: #fff;
border: 1px solid #ddd;
border-radius: 3px;
text-decoration: none;
color: #333;
}
.search-sorting-options a:hover,
.search-sorting-options a.active {
background: #0073aa;
color: white;
border-color: #0073aa;
}
</style>
<?php
}
}
add_action( 'before_search_results', 'add_search_sorting_options' );
// 如果主题没有这个hook,可以在search.php模板中添加:do_action('before_search_results');
方案三:不使用插件,完全自定义浏览量统计 + 排序
步骤1:添加浏览量统计功能
/**
* 记录文章浏览量(不依赖插件)
*/
function track_post_views( $post_id ) {
if ( ! is_single() ) return;
if ( empty( $post_id ) ) {
global $post;
$post_id = $post->ID;
}
$count_key = 'post_views_count';
$count = get_post_meta( $post_id, $count_key, true );
if ( $count == '' ) {
$count = 0;
delete_post_meta( $post_id, $count_key );
add_post_meta( $post_id, $count_key, '1' );
} else {
$count++;
update_post_meta( $post_id, $count_key, $count );
}
}
// 移除这个动作钩子,如果你不希望在预览时统计
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
// 在single.php中调用
function get_post_views( $post_id ) {
$count_key = 'post_views_count';
$count = get_post_meta( $post_id, $count_key, true );
if ( $count == '' ) {
delete_post_meta( $post_id, $count_key );
add_post_meta( $post_id, $count_key, '0' );
return 0;
}
return $count;
}
步骤2:在single.php模板中显示和统计
在 single.php的合适位置添加:
<?php
// 显示浏览量
echo '浏览:' . get_post_views( get_the_ID() );
// 统计浏览量(放在文章内容之后)
track_post_views( get_the_ID() );
?>
步骤3:修改搜索查询
/**
* 搜索结果按自定义浏览量排序
*/
function custom_search_orderby_views( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
$order = isset( $_GET['order'] ) ? $_GET['order'] : 'view_desc';
switch ( $order ) {
case 'view_desc':
$query->set( 'meta_key', 'post_views_count' );
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'order', 'DESC' );
break;
case 'view_asc':
$query->set( 'meta_key', 'post_views_count' );
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'order', 'ASC' );
break;
}
}
}
add_action( 'pre_get_posts', 'custom_search_orderby_views' );
方案四:高级实现 – 带AJAX的实时搜索排序
创建一个更高级的搜索排序系统:
/**
* 增强版搜索排序系统
*/
class Advanced_Search_Sorter {
public function __construct() {
add_action( 'pre_get_posts', array( $this, 'modify_search_query' ) );
add_action( 'wp_ajax_search_sort', array( $this, 'ajax_search_results' ) );
add_action( 'wp_ajax_nopriv_search_sort', array( $this, 'ajax_search_results' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
/**
* 修改搜索结果查询
*/
public function modify_search_query( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) {
$sort_by = get_query_var( 'sort_by', 'relevance' );
if ( $sort_by === 'views_desc' ) {
$query->set( 'meta_key', 'post_views_count' );
$query->set( 'orderby', array(
'meta_value_num' => 'DESC',
'date' => 'DESC'
) );
} elseif ( $sort_by === 'views_asc' ) {
$query->set( 'meta_key', 'post_views_count' );
$query->set( 'orderby', array(
'meta_value_num' => 'ASC',
'date' => 'DESC'
) );
}
}
}
/**
* 添加排序参数到查询变量
*/
public function add_query_vars( $vars ) {
$vars[] = 'sort_by';
return $vars;
}
/**
* 注册脚本
*/
public function enqueue_scripts() {
if ( is_search() ) {
wp_enqueue_script( 'search-sorter', get_template_directory_uri() . '/js/search-sorter.js', array( 'jquery' ), '1.0', true );
wp_localize_script( 'search-sorter', 'searchSorter', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'search_sort_nonce' )
) );
}
}
/**
* AJAX获取排序结果
*/
public function ajax_search_results() {
check_ajax_referer( 'search_sort_nonce', 'nonce' );
$search_query = sanitize_text_field( $_POST['s'] );
$sort_by = sanitize_text_field( $_POST['sort_by'] );
$paged = intval( $_POST['paged'] ) ?: 1;
$args = array(
's' => $search_query,
'post_type' => 'post',
'posts_per_page' => 10,
'paged' => $paged,
'post_status' => 'publish'
);
// 设置排序
switch ( $sort_by ) {
case 'views_desc':
$args['meta_key'] = 'post_views_count';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
case 'date_desc':
$args['orderby'] = 'date';
$args['order'] = 'DESC';
break;
case 'relevance':
default:
// 使用默认相关性排序
break;
}
$query = new WP_Query( $args );
ob_start();
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
?>
<article class="search-result-item">
<h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<div class="post-meta">
<span class="views">浏览:<?php echo get_post_views( get_the_ID() ); ?></span>
<span class="date"><?php echo get_the_date(); ?></span>
</div>
<div class="excerpt"><?php the_excerpt(); ?></div>
</article>
<?php
}
// 分页
if ( $query->max_num_pages > 1 ) {
echo '<div class="search-pagination">';
echo paginate_links( array(
'base' => add_query_arg( 'paged', '%#%' ),
'format' => '',
'current' => $paged,
'total' => $query->max_num_pages
) );
echo '</div>';
}
} else {
echo '<p>没有找到相关结果。</p>';
}
wp_reset_postdata();
$output = ob_get_clean();
wp_send_json_success( array( 'html' => $output ) );
}
/**
* 显示排序控件
*/
public static function display_sort_controls() {
if ( ! is_search() ) return;
$current_sort = get_query_var( 'sort_by', 'relevance' );
$search_query = get_search_query();
?>
<div class="search-sort-controls">
<select id="search-sort-select" data-search="<?php echo esc_attr( $search_query ); ?>">
<option value="relevance" <?php selected( $current_sort, 'relevance' ); ?>>
按相关度排序
</option>
<option value="views_desc" <?php selected( $current_sort, 'views_desc' ); ?>>
按浏览量(高→低)
</option>
<option value="date_desc" <?php selected( $current_sort, 'date_desc' ); ?>>
按时间(新→旧)
</option>
</select>
<div class="sort-links">
<a href="<?php echo esc_url( add_query_arg( 'sort_by', 'relevance' ) ); ?>"
class="<?php echo $current_sort === 'relevance' ? 'active' : ''; ?>">
相关度
</a>
<a href="<?php echo esc_url( add_query_arg( 'sort_by', 'views_desc' ) ); ?>"
class="<?php echo $current_sort === 'views_desc' ? 'active' : ''; ?>">
浏览量
</a>
<a href="<?php echo esc_url( add_query_arg( 'sort_by', 'date_desc' ) ); ?>"
class="<?php echo $current_sort === 'date_desc' ? 'active' : ''; ?>">
最新
</a>
</div>
</div>
<style>
.search-sort-controls {
margin: 20px 0;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
display: flex;
justify-content: space-between;
align-items: center;
}
#search-sort-select {
padding: 8px 15px;
border: 2px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.sort-links a {
margin-left: 15px;
padding: 8px 20px;
background: white;
border: 2px solid #ddd;
border-radius: 4px;
text-decoration: none;
color: #555;
font-weight: 500;
}
.sort-links a:hover,
.sort-links a.active {
background: #0073aa;
color: white;
border-color: #0073aa;
}
</style>
<?php
}
}
// 初始化
new Advanced_Search_Sorter();
add_filter( 'query_vars', array( 'Advanced_Search_Sorter', 'add_query_vars' ) );
add_action( 'before_search_results', array( 'Advanced_Search_Sorter', 'display_sort_controls' ) );
对应的JavaScript文件 (search-sorter.js)
jQuery(document).ready(function($) {
// 下拉选择排序
$('#search-sort-select').on('change', function() {
var sortBy = $(this).val();
var searchQuery = $(this).data('search');
$.ajax({
url: searchSorter.ajaxurl,
type: 'POST',
data: {
action: 'search_sort',
nonce: searchSorter.nonce,
s: searchQuery,
sort_by: sortBy,
paged: 1
},
beforeSend: function() {
$('.search-results').html('<div class="loading">加载中...</div>');
},
success: function(response) {
if (response.success) {
$('.search-results').html(response.data.html);
// 更新URL(不刷新页面)
var newUrl = window.location.pathname + '?s=' + encodeURIComponent(searchQuery) + '&sort_by=' + sortBy;
window.history.pushState({path: newUrl}, '', newUrl);
}
}
});
});
// 处理分页链接的AJAX
$(document).on('click', '.search-pagination a', function(e) {
e.preventDefault();
var pageUrl = $(this).attr('href');
var pageNum = getParameterByName('paged', pageUrl) || 1;
var sortBy = getParameterByName('sort_by', window.location.href) || 'relevance';
var searchQuery = getParameterByName('s', window.location.href);
$.ajax({
url: searchSorter.ajaxurl,
type: 'POST',
data: {
action: 'search_sort',
nonce: searchSorter.nonce,
s: searchQuery,
sort_by: sortBy,
paged: pageNum
},
beforeSend: function() {
$('.search-results').html('<div class="loading">加载中...</div>');
},
success: function(response) {
if (response.success) {
$('.search-results').html(response.data.html);
}
}
});
});
// 从URL获取参数
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
});
使用建议
- 新手/快速上线:使用方案一(插件组合),最稳定
- 有一定开发能力:使用方案二,配合现有WP-PostViews插件
- 需要完全自定义:使用方案三,不依赖任何插件
- 需要最佳用户体验:使用方案四,支持AJAX无刷新排序
注意事项
- 性能考虑:浏览量大的站点,考虑使用缓存或定期更新排序索引
- SEO优化:为排序链接添加
rel="nofollow",避免蜘蛛重复爬取 - 数据准确性:考虑排除机器人访问,确保浏览量数据真实
- 移动端适配:确保排序控件在移动设备上可用



湘公网安备43020002000238