PHP项目怎样实现评论置顶功能?

wen PHP项目 32

本文目录导读:

PHP项目怎样实现评论置顶功能?

  1. 核心思路
  2. 数据库设计
  3. 后端PHP逻辑
  4. 前端交互
  5. 完整流程总结
  6. 进阶优化建议

在PHP项目中实现评论置顶功能,通常需要在数据库设计、后端逻辑和前端展示三个层面进行改造,下面给你一个清晰、完整的实现方案。

核心思路

为评论表增加一个is_pinned(是否置顶)字段和一个pinned_at(置顶时间)字段,查询时,优先按置顶状态排序(置顶的排在前面),再按置顶时间或常规时间排序。


数据库设计

假设你已有评论表 comments,需要添加两个字段:

ALTER TABLE `comments` 
ADD COLUMN `is_pinned` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否置顶:0=否,1=是',
ADD COLUMN `pinned_at` DATETIME DEFAULT NULL COMMENT '置顶时间(用于排序)';

字段说明:

  • is_pinned:标记该评论是否被置顶。
  • pinned_at:记录置顶操作的时间,当取消置顶时,可以设为 NULL,这个字段用于在多个置顶评论之间排序(最新置顶的排最前面)。

后端PHP逻辑

1 查询评论(核心排序逻辑)

/**
 * 获取某篇文章的评论列表(置顶优先)
 *
 * @param int $articleId 文章ID
 * @return array
 */
function getComments(int $articleId): array {
    $db = getDbConnection(); // 你的数据库连接函数
    $sql = "SELECT * FROM comments 
            WHERE article_id = ? 
            ORDER BY 
                is_pinned DESC, 
                COALESCE(pinned_at, created_at) DESC";
    $stmt = $db->prepare($sql);
    $stmt->execute([$articleId]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

排序逻辑解释:

  • is_pinned DESC:先按置顶状态降序,置顶的(1)排在非置顶的(0)前面。
  • COALESCE(pinned_at, created_at) DESCpinned_at 不为空(已置顶),则按置顶时间排序;否则按评论创建时间排序,这样多个置顶评论可以按置顶的先后顺序排列。

2 置顶/取消置顶接口

置顶操作:

/**
 * 置顶某条评论
 *
 * @param int $commentId 评论ID
 * @return bool
 */
function pinComment(int $commentId): bool {
    $db = getDbConnection();
    $sql = "UPDATE comments 
            SET is_pinned = 1, pinned_at = NOW() 
            WHERE id = ? AND is_pinned = 0";
    $stmt = $db->prepare($sql);
    return $stmt->execute([$commentId]);
}

取消置顶操作:

/**
 * 取消置顶某条评论
 *
 * @param int $commentId 评论ID
 * @return bool
 */
function unpinComment(int $commentId): bool {
    $db = getDbConnection();
    $sql = "UPDATE comments 
            SET is_pinned = 0, pinned_at = NULL 
            WHERE id = ? AND is_pinned = 1";
    $stmt = $db->prepare($sql);
    return $stmt->execute([$commentId]);
}

3 权限控制

置顶操作通常仅限管理员或文章作者,建议在调用上面两个函数前,先校验用户权限:

function canPinComment(int $userId, int $commentId): bool {
    // 1. 检查用户是否是超级管理员
    if (isAdmin($userId)) {
        return true;
    }
    // 2. 检查用户是否是文章作者(需要联表查询)
    $db = getDbConnection();
    $sql = "SELECT a.user_id 
            FROM comments c 
            JOIN articles a ON c.article_id = a.id 
            WHERE c.id = ?";
    $stmt = $db->prepare($sql);
    $stmt->execute([$commentId]);
    $article = $stmt->fetch();
    return $article && $article['user_id'] == $userId;
}

前端交互

1 管理员界面添加操作按钮

在每条评论的管理操作区,根据当前状态显示不同的按钮:

<!-- 仅管理员可见 -->
<div class="comment-actions">
    <?php if ($comment['is_pinned']): ?>
        <button class="btn-unpin" data-comment-id="<?= $comment['id'] ?>">取消置顶</button>
    <?php else: ?>
        <button class="btn-pin" data-comment-id="<?= $comment['id'] ?>">置顶</button>
    <?php endif; ?>
</div>

2 使用Ajax发送请求(提升用户体验)

// 使用 jQuery 示例
$('.btn-pin, .btn-unpin').on('click', function() {
    const commentId = $(this).data('comment-id');
    const action = $(this).hasClass('btn-pin') ? 'pin' : 'unpin';
    const button = $(this);
    $.ajax({
        url: '/api/comment/togglePin',
        method: 'POST',
        data: {
            comment_id: commentId,
            action: action,
            _token: '<?= csrf_token() ?>' // CSRF 防护
        },
        success: function(response) {
            if (response.success) {
                // 更新按钮状态和文本
                if (action === 'pin') {
                    button.text('取消置顶').removeClass('btn-pin').addClass('btn-unpin');
                } else {
                    button.text('置顶').removeClass('btn-unpin').addClass('btn-pin');
                }
                // 可选:重新加载评论列表或刷新页面
                location.reload();
            } else {
                alert('操作失败:' + response.message);
            }
        },
        error: function() {
            alert('网络错误,请重试');
        }
    });
});

3 前端显示置顶标识

在渲染评论列表时,对于 is_pinned = 1 的评论,可以添加特殊样式:

<div class="comment-item <?= $comment['is_pinned'] ? 'pinned' : '' ?>">
    <?php if ($comment['is_pinned']): ?>
        <span class="pinned-badge">📌 置顶</span>
    <?php endif; ?>
    <!-- 评论内容 -->
</div>

CSS 样式示例:

.comment-item.pinned {
    background-color: #f8f9fa;
    border-left: 4px solid #ffc107;
    padding-left: 12px;
}
.pinned-badge {
    color: #ffc107;
    font-weight: bold;
    margin-right: 8px;
}

完整流程总结

  1. 数据库准备:添加 is_pinnedpinned_at 字段。
  2. 查询排序ORDER BY is_pinned DESC, COALESCE(pinned_at, created_at) DESC
  3. 权限校验:只在管理员或作者可操作。
  4. 接口开发:提供 pin/unpin 的 API(更新字段 + 记录时间)。
  5. 前端交互:添加操作按钮(Ajax 无刷新)和置顶标识样式。

进阶优化建议

  • 只允许固定数量置顶:例如最多置顶 3 条,可以在 pinComment() 函数中先查询当前置顶数量。
  • 缓存置顶评论:对于高并发场景,可以将置顶评论缓存到 Redis,减少数据库查询。
  • 支持置顶排序:如果需要手动调整置顶间的顺序,可以再加一个 pin_order 字段(TINYINTINT)。
  • 后台管理功能:在后台评论列表增加“置顶/取消置顶”的批量操作。

如果还有具体实现中的细节问题,欢迎继续提问。

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