
在传统的web应用中,当数据量较大时,通常会采用分页技术来提高页面加载速度和用户体验。前端分页(如通过javascript操作dom)和后端分页是两种常见模式。原有的实现中,分页逻辑在后端处理,每次只从数据库查询并显示一页数据。然而,搜索功能却完全依赖前端javascript myfunction() 来过滤当前页面已加载的表格行。
这种实现方式的根本问题在于:JavaScript只能操作浏览器当前可见的DOM元素。当用户搜索时,它只能在当前显示的10条(或设定的每页记录数)数据中进行匹配和过滤。对于未加载到当前页面的数据,前端JavaScript无从得知,因此无法实现“全站”或“所有分页”的搜索。要实现对所有数据的搜索,必须让数据库参与到搜索过程中,即在数据被分页之前就完成过滤。
解决此问题的关键在于将搜索逻辑转移到服务器端。这意味着:
首先,我们需要修改PHP代码,使其能够接收并处理来自URL的搜索关键词。通常,我们会将搜索关键词通过GET请求参数传递,例如 ?page=1&s=keyword。
在页面的顶部(处理分页逻辑之前),添加对搜索关键词的获取和处理:
立即学习“PHP免费学习笔记(深入)”;
<?php
// 数据库连接 $conn 假设已建立
// 获取当前页码
if (isset($_GET['page']) && $_GET['page'] != "") {
$page = $_GET['page'];
} else {
$page = 1;
}
// 获取搜索关键词
$search_query = "";
if (isset($_GET['s']) && $_GET['s'] != "") {
$search_query = mysqli_real_escape_string($conn, $_GET['s']); // 对搜索关键词进行转义,防止SQL注入
}
$total_records_per_page = 10;
$offset = ($page - 1) * $total_records_per_page;
$previous_page = $page - 1;
$next_page = $page + 1;
$adjacents = "2"; // 用于控制分页链接的显示数量
// 构建SQL WHERE子句,如果存在搜索关键词
$where_clause = "";
if (!empty($search_query)) {
// 假设您想在 'snapchat' 表的 'name' 和 'description' 列中搜索
// 请根据您的实际表结构和需要搜索的列进行调整
$where_clause = " WHERE `name` LIKE '%" . $search_query . "%' OR `description` LIKE '%" . $search_query . "%'";
// 更好的做法是使用预处理语句,防止SQL注入,如下所示
// $where_clause = " WHERE `name` LIKE ? OR `description` LIKE ?";
}
// 获取符合条件的总记录数
$count_sql = "SELECT COUNT(*) As total_records FROM `snapchat`" . $where_clause;
$result_count = mysqli_query($conn, $count_sql);
// 如果使用预处理语句,则需要如下方式
// $stmt_count = mysqli_prepare($conn, "SELECT COUNT(*) As total_records FROM `snapchat`" . $where_clause);
// if (!empty($search_query)) {
// $param_search = '%' . $search_query . '%';
// mysqli_stmt_bind_param($stmt_count, "ss", $param_search, $param_search);
// }
// mysqli_stmt_execute($stmt_count);
// $result_count = mysqli_stmt_get_result($stmt_count);
$total_records = mysqli_fetch_array($result_count)['total_records'];
$total_no_of_pages = ceil($total_records / $total_records_per_page);
$second_last = $total_no_of_pages - 1;
// 获取当前页的数据
$data_sql = "SELECT * FROM `snapchat`" . $where_clause . " LIMIT " . $offset . ", " . $total_records_per_page;
$result_data = mysqli_query($conn, $data_sql);
// 如果使用预处理语句,则需要如下方式
// $stmt_data = mysqli_prepare($conn, "SELECT * FROM `snapchat`" . $where_clause . " LIMIT ?, ?");
// if (!empty($search_query)) {
// $param_search = '%' . $search_query . '%';
// mysqli_stmt_bind_param($stmt_data, "ssii", $param_search, $param_search, $offset, $total_records_per_page);
// } else {
// mysqli_stmt_bind_param($stmt_data, "ii", $offset, $total_records_per_page);
// }
// mysqli_stmt_execute($stmt_data);
// $result_data = mysqli_stmt_get_result($stmt_data);
// 此时 $result_data 包含了当前页经过搜索过滤后的数据,可以在表格中显示
?>重要提示: 上述代码中使用了 mysqli_real_escape_string 来防止SQL注入。然而,更安全和推荐的做法是使用预处理语句 (Prepared Statements)。在注释中提供了预处理语句的示例,建议在生产环境中采用。
如上所示,我们在获取总记录数 (COUNT(*)) 和获取当前页数据 (SELECT *) 的SQL查询中都加入了 $where_clause。这样,无论是计算总页数还是获取具体数据,都将只针对符合搜索条件的结果进行。
为了确保在用户点击分页链接时,搜索条件能够被保留,我们需要在生成分页链接的URL中加入搜索关键词参数 s。
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center">
<?php
// 构建基础URL参数,保留搜索关键词
$base_url_params = "";
if (!empty($search_query)) {
$base_url_params = "&s=" . urlencode($search_query); // 使用urlencode确保关键词在URL中正确编码
}
?>
<li <?php if($page <= 1){ echo "class='page-item page-link disabled' style='color:black;'"; } ?>>
<a <?php if($page > 1){ echo "class='page-link' href='?page=$previous_page" . $base_url_params . "'"; } ?>>Poprzednia</a>
</li>
<?php
if ($total_no_of_pages <= 10){
for ($counter = 1; $counter <= $total_no_of_pages; $counter++){
if ($counter == $page) {
echo "<li class='page-item active'><a class='page-link'>$counter</a></li>";
}else{
echo "<li class='page-item'><a class='page-link' href='?page=$counter" . $base_url_params . "'>$counter</a></li>";
}
}
}
elseif($total_no_of_pages > 10){
if($page <= 4) {
for ($counter = 1; $counter < 8; $counter++){
if ($counter == $page) {
echo "<li class='page-item active'><a class='page-link'>$counter</a></li>";
}else{
echo "<li class='page-item'><a class='page-link' href='?page=$counter" . $base_url_params . "'>$counter</a></li>";
}
}
echo "<li class='page-item'><a class='page-link'>...</a></li>";
echo "<li class='page-item'><a class='page-link' href='?page=$second_last" . $base_url_params . "'>$second_last</a></li>";
echo "<li class='page-item'><a class='page-link' href='?page=$total_no_of_pages" . $base_url_params . "'>$total_no_of_pages</a></li>";
}
elseif($page > 4 && $page < $total_no_of_pages - 4) {
echo "<li class='page-item'><a class='page-link' href='?page=1" . $base_url_params . "'>1</a></li>";
echo "<li class='page-item'><a class='page-link' href='?page=2" . $base_url_params . "'>2</a></li>";
echo "<li class='page-item'><a class='page-link'>...</a></li>";
for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++) {
if ($counter == $page) {
echo "<li class='page-item active'><a class='page-link'>$counter</a></li>";
}else{
echo "<li class='page-item'><a class='page-link' href='?page=$counter" . $base_url_params . "'>$counter</a></li>";
}
}
echo "<li class='page-item'><a class='page-link'>...</a></li>";
echo "<li class='page-item'><a class='page-link' href='?page=$second_last" . $base_url_params . "'>$second_last</a></li>";
echo "<li class='page-item'><a class='page-link' href='?page=$total_no_of_pages" . $base_url_params . "'>$total_no_of_pages</a></li>";
}
else {
echo "<li class='page-item'><a class='page-link' href='?page=1" . $base_url_params . "'>1</a></li>";
echo "<li class='page-item'><a class='page-link' href='?page=2" . $base_url_params . "'>2</a></li>";
echo "<li class='page-item'><a class='page-link'>...</a></li>";
for ($counter = $total_no_of_pages - 6; $counter <= $total_no_of_pages; $counter++) {
if ($counter == $page) {
echo "<li class='page-item active'><a class='page-link'>$counter</a></li>";
}else{
echo "<li class='page-item'><a class='page-link' href='?page=$counter" . $base_url_params . "'>$counter</a></li>";
}
}
}
}
?>
<li <?php if($page >= $total_no_of_pages){ echo "class='page-item page-link disabled' style='color:black;'"; } ?>>
<a <?php if($page < $total_no_of_pages) { echo "class='page-link' href='?page=$next_page" . $base_url_params . "'"; } ?>>Następna</a>
</li>
<?php if($page < $total_no_of_pages){
echo "<li class='page-item'><a class='page-link' href='?page=$total_no_of_pages" . $base_url_params . "'>Ostatnia ››</a></li>";
} ?>
</ul>
</nav>在搜索输入框部分,将 onkeyup="myFunction()" 替换为提交表单或直接跳转URL的方式:
<!-- 搜索输入框 -->
<form method="GET" action="">
<input type="text" id="myInput" name="s" placeholder="搜索..." value="<?php echo htmlspecialchars($search_query); ?>">
<input type="hidden" name="page" value="1"> <!-- 搜索时默认回到第一页 -->
<button type="submit">搜索</button>
</form>或者,如果希望实时搜索(不刷新页面),可以使用JavaScript监听输入框,并在输入变化时通过Ajax将关键词发送到服务器,然后服务器返回新的分页数据和分页链接HTML,再由前端动态更新。但这超出了本教程的范围,本教程专注于传统的GET请求方式。
由于搜索逻辑已完全转移到后端,原有的 myFunction() JavaScript代码不再需要用于全局搜索。它可以被完全移除,或者仅用于在当前已加载数据中进行快速的客户端过滤(如果仍有此需求,但与后端搜索功能是独立的)。对于实现“从所有页面搜索”的目标,myFunction() 已无用。
通过将搜索逻辑从前端迁移到后端,我们不仅解决了“只搜索当前页”的问题,还为构建更健壮、安全和高效的数据查询系统奠定了基础。
以上就是PHP/MySQL分页数据的高效全站搜索实现的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号