PHP项目怎么实现商品评价筛选?

wen PHP项目 54

本文目录导读:

PHP项目怎么实现商品评价筛选?

  1. 核心思路:动态构建 SQL 查询
  2. 数据库设计示例
  3. 后端 PHP 实现 (动态SQL拼装)
  4. 前端实现(HTML + JavaScript + AJAX)
  5. 进阶优化与注意事项
  6. 总结流程图

在 PHP 项目中实现商品评价筛选,核心是根据用户选择的条件(如评分、时间、内容关键词、是否有图/追评等)动态构建 SQL 查询

以下是一个从简单到复杂的实现方案,包含前后端交互的完整逻辑。

核心思路:动态构建 SQL 查询

用户在前端选择筛选条件后将参数发送到后端,后端根据接收到的参数拼接 WHERE 子句。

典型的筛选条件:

  • 评分范围 (1-5星)
  • 评价时间 (最近一周/月/半年)
  • 评价类型 (全部 / 有图 / 无图 / 有追评)
  • 排序方式 (最新 / 最有帮助 / 评分最高/最低)

数据库设计示例

假设你有一个 reviews 表:

CREATE TABLE `reviews` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `product_id` int(11) NOT NULL COMMENT '商品ID',
  `user_id` int(11) NOT NULL,
  `rating` tinyint(1) NOT NULL COMMENT '评分 1-5',
  `content` text COMMENT '评价内容',
  `images` varchar(255) DEFAULT NULL COMMENT '图片,逗号分隔',
  `created_at` datetime NOT NULL,
  `updated_at` datetime DEFAULT NULL COMMENT '追评时间',
  `helpful_count` int(11) DEFAULT 0 COMMENT '点赞数',
  PRIMARY KEY (`id`),
  KEY `product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

后端 PHP 实现 (动态SQL拼装)

这是最关键的代码逻辑,假设你使用的是 PDO(推荐)或 MySQLi。

文件: api/get_reviews.php

<?php
// 假设已经建立了数据库连接 $db_connection (PDO)
$productId = intval($_GET['product_id'] ?? 0);
$rating = intval($_GET['rating'] ?? 0);        // 0 表示全部
$hasImage = intval($_GET['has_image'] ?? 0);   // 0:全部 1:有图 -1:无图
$hasAppend = intval($_GET['has_append'] ?? 0); // 0:全部 1:有追评
$orderBy = $_GET['order_by'] ?? 'latest';      // latest, highest, lowest, helpful
$keyword = trim($_GET['keyword'] ?? '');        // 内容搜索 (可选)
$page = max(1, intval($_GET['page'] ?? 1));
$pageSize = 10;
// ----- 1. 基础 WHERE 条件 -----
$where = "WHERE product_id = :product_id"; // 必须条件
$params = [':product_id' => $productId];
// 评分筛选
if ($rating >= 1 && $rating <= 5) {
    $where .= " AND rating = :rating";
    $params[':rating'] = $rating;
}
// 有图/无图筛选
if ($hasImage === 1) {
    $where .= " AND images IS NOT NULL AND images != ''";
} elseif ($hasImage === -1) { // 注意:-1 表示无图
    $where .= " AND (images IS NULL OR images = '')";
}
// 追评筛选
if ($hasAppend === 1) {
    $where .= " AND updated_at IS NOT NULL"; // 假设追评会更新更新时间
}
// 关键词搜索 (防止SQL注入,使用LIKE)
if (!empty($keyword)) {
    $where .= " AND content LIKE :keyword";
    $params[':keyword'] = '%' . $keyword . '%';
}
// ----- 2. 排序 -----
switch ($orderBy) {
    case 'highest':
        $orderSQL = "ORDER BY rating DESC, created_at DESC";
        break;
    case 'lowest':
        $orderSQL = "ORDER BY rating ASC, created_at DESC";
        break;
    case 'helpful':
        $orderSQL = "ORDER BY helpful_count DESC, created_at DESC";
        break;
    case 'latest':
    default:
        $orderSQL = "ORDER BY created_at DESC";
        break;
}
// ----- 3. 分页 -----
$offset = ($page - 1) * $pageSize;
$limitSQL = "LIMIT :limit OFFSET :offset";
$params[':limit'] = $pageSize;
$params[':offset'] = $offset;
// ----- 4. 执行查询 -----
$sql = "SELECT * FROM reviews {$where} {$orderSQL} {$limitSQL}";
$stmt = $db_connection->prepare($sql);
// 绑定参数 (注意分页参数类型)
foreach ($params as $key => $value) {
    if ($key === ':limit' || $key === ':offset') {
        $stmt->bindValue($key, $value, PDO::PARAM_INT);
    } else {
        $stmt->bindValue($key, $value);
    }
}
$stmt->execute();
$reviews = $stmt->fetchAll(PDO::FETCH_ASSOC);
// ----- 5. 获取总数量 (用于分页) -----
$countSql = "SELECT COUNT(*) as total FROM reviews {$where}";
$countStmt = $db_connection->prepare($countSql);
foreach ($params as $key => $value) {
    // 注意:count查询的SQL不包含limit参数,需要过滤掉
    if ($key === ':limit' || $key === ':offset') {
        continue;
    }
    $countStmt->bindValue($key, $value);
}
$countStmt->execute();
$total = $countStmt->fetch(PDO::FETCH_ASSOC)['total'];
// ----- 6. 返回JSON数据 -----
header('Content-Type: application/json');
echo json_encode([
    'code' => 200,
    'data' => $reviews,
    'total' => $total,
    'page' => $page,
    'page_size' => $pageSize
]);

前端实现(HTML + JavaScript + AJAX)

前端负责捕获用户操作,发起异步请求并渲染结果。

文件: product_detail.php (简化版)

<!DOCTYPE html>
<html>
<head>商品评价</title>
</head>
<body>
    <h1>商品详情</h1>
    <!-- 筛选区 -->
    <div id="filter-area">
        <select id="rating-filter">
            <option value="0">全部评分</option>
            <option value="5">5星</option>
            <option value="4">4星</option>
            <option value="3">3星</option>
            <option value="2">2星</option>
            <option value="1">1星</option>
        </select>
        <select id="image-filter">
            <option value="0">全部评价</option>
            <option value="1">有图评价</option>
            <option value="-1">无图评价</option>
        </select>
        <select id="order-filter">
            <option value="latest">最新</option>
            <option value="helpful">最有帮助</option>
        </select>
        <button id="apply-filter">筛选</button>
    </div>
    <!-- 评价列表 -->
    <div id="review-list"></div>
    <!-- 分页 -->
    <div id="pagination"></div>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
        $(document).ready(function() {
            let currentPage = 1;
            const productId = 123; // 从页面获取实际商品ID
            function loadReviews(page) {
                currentPage = page || 1;
                // 收集筛选条件
                const params = {
                    product_id: productId,
                    rating: $('#rating-filter').val(),
                    has_image: $('#image-filter').val(),
                    order_by: $('#order-filter').val(),
                    page: currentPage
                };
                $.get('/api/get_reviews.php', params, function(response) {
                    if (response.code === 200) {
                        renderReviews(response.data);
                        renderPagination(response.total, response.page, response.page_size);
                    }
                }, 'json');
            }
            function renderReviews(reviews) {
                let html = '';
                reviews.forEach(function(review) {
                    html += `<div class="review-item">
                                <div>评分: ${'★'.repeat(review.rating)}${'☆'.repeat(5-review.rating)}</div>
                                <p>${review.content}</p>
                                <small>${review.created_at}</small>
                            </div>`;
                });
                $('#review-list').html(html);
            }
            // 绑定筛选按钮点击
            $('#apply-filter').click(function() {
                loadReviews(1); // 重新筛选时回到第一页
            });
            // 初始加载
            loadReviews(1);
        });
    </script>
</body>
</html>

进阶优化与注意事项

  1. 避免 SQL 注入
    • 永远不要直接拼接用户输入到SQL中。
    • 使用预处理语句(Prepared Statement)是标准做法。
  2. 使用全文索引(性能优化)
    • 如果关键词搜索非常频繁,可以考虑对 content 字段建立 MySQL 的 FULLTEXT 索引,然后使用 MATCH...AGAINST 替代 LIKE(性能更好)。
  3. 筛选统计(用户体验)
    • 很多电商网站会显示“全部 500条”、“有图 30条”,可以用一个 SQL 在加载时一次性统计。
      SELECT 
          COUNT(*) as total,
          SUM(CASE WHEN images != '' THEN 1 ELSE 0 END) as has_images,
          SUM(CASE WHEN rating = 5 THEN 1 ELSE 0 END) as five_star
      FROM reviews WHERE product_id = ?
  4. 分页安全
    • 防止 page 参数过大导致数据库压力或返回大量无效页码。
  5. Redis 缓存(高并发场景)

    对于同一个商品的评价筛选结果(尤其是评分、有图这类变化不频繁的筛选),可以缓存到 Redis 中,设置5分钟过期,可以有效降低数据库压力。

总结流程图

用户操作 (点击筛选/排序) 
    ↓
前端JS(收集参数) 
    ↓
AJAX请求 (GET /api/reviews)
    ↓
PHP接收参数  
    ↓
安全验证 并 动态拼接SQL WHERE/ORDER BY/LIMIT 
    ↓
PDO预处理 + 参数绑定  
    ↓
执行SQL → 获取数据  
    ↓
返回JSON (包含评价列表 + 总数)
    ↓
前端渲染HTML

这样,一个完整的、安全的、可扩展的商品评价筛选功能就实现了。

抱歉,评论功能暂时关闭!