PHP项目怎样实现内容点赞取消?

wen PHP项目 32

本文目录导读:

PHP项目怎样实现内容点赞取消?

  1. 数据库设计
  2. PHP后端实现
  3. 前端实现
  4. 前端CSS样式
  5. 优化建议
  6. 完整示例代码

在PHP项目中实现点赞/取消点赞功能,通常需要结合数据库和前端交互,以下是完整的实现方案:

数据库设计

创建一个点赞记录表:

CREATE TABLE likes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT NOT NULL COMMENT '用户ID',
    content_id INT NOT NULL COMMENT '内容ID',
    content_type VARCHAR(50) NOT NULL COMMENT '内容类型,如article, comment等',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_like (user_id, content_id, content_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

表(如articles)中添加点赞数字段:

ALTER TABLE articles ADD COLUMN likes_count INT DEFAULT 0;

PHP后端实现

点赞/取消点赞接口

<?php
// like.php
session_start();
require_once 'db.php'; // 数据库连接文件
header('Content-Type: application/json');
if (!isset($_SESSION['user_id'])) {
    echo json_encode(['success' => false, 'message' => '请先登录']);
    exit;
}
$user_id = $_SESSION['user_id'];
$content_id = intval($_POST['content_id']);
$content_type = $_POST['content_type'] ?? 'article';
// 检查是否已点赞
$stmt = $pdo->prepare("SELECT id FROM likes WHERE user_id = ? AND content_id = ? AND content_type = ?");
$stmt->execute([$user_id, $content_id, $content_type]);
$like = $stmt->fetch();
if ($like) {
    // 已点赞,取消点赞
    $pdo->beginTransaction();
    try {
        // 删除点赞记录
        $stmt = $pdo->prepare("DELETE FROM likes WHERE id = ?");
        $stmt->execute([$like['id']]);
        // 更新内容点赞数
        $table = $content_type == 'article' ? 'articles' : 'comments';
        $stmt = $pdo->prepare("UPDATE $table SET likes_count = likes_count - 1 WHERE id = ?");
        $stmt->execute([$content_id]);
        $pdo->commit();
        echo json_encode([
            'success' => true, 
            'liked' => false,
            'likes_count' => getLikesCount($pdo, $content_id, $content_type)
        ]);
    } catch (Exception $e) {
        $pdo->rollBack();
        echo json_encode(['success' => false, 'message' => '操作失败']);
    }
} else {
    // 未点赞,执行点赞
    $pdo->beginTransaction();
    try {
        // 添加点赞记录
        $stmt = $pdo->prepare("INSERT INTO likes (user_id, content_id, content_type) VALUES (?, ?, ?)");
        $stmt->execute([$user_id, $content_id, $content_type]);
        // 更新内容点赞数
        $table = $content_type == 'article' ? 'articles' : 'comments';
        $stmt = $pdo->prepare("UPDATE $table SET likes_count = likes_count + 1 WHERE id = ?");
        $stmt->execute([$content_id]);
        $pdo->commit();
        echo json_encode([
            'success' => true, 
            'liked' => true,
            'likes_count' => getLikesCount($pdo, $content_id, $content_type)
        ]);
    } catch (Exception $e) {
        $pdo->rollBack();
        echo json_encode(['success' => false, 'message' => '操作失败']);
    }
}
function getLikesCount($pdo, $content_id, $content_type) {
    $table = $content_type == 'article' ? 'articles' : 'comments';
    $stmt = $pdo->prepare("SELECT likes_count FROM $table WHERE id = ?");
    $stmt->execute([$content_id]);
    return $stmt->fetchColumn();
}
?>

前端实现

HTML结构

<div class="like-container">
    <button class="like-btn" data-content-id="123" data-content-type="article">
        <i class="heart-icon">❤</i>
        <span class="likes-count">0</span>
    </button>
</div>

JavaScript交互

// 使用原生JavaScript
document.querySelectorAll('.like-btn').forEach(btn => {
    btn.addEventListener('click', function() {
        const contentId = this.dataset.contentId;
        const contentType = this.dataset.contentType;
        // 发送AJAX请求
        fetch('like.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: `content_id=${contentId}&content_type=${contentType}`
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                // 更新UI
                const heartIcon = this.querySelector('.heart-icon');
                const countSpan = this.querySelector('.likes-count');
                // 切换点赞状态
                if (data.liked) {
                    this.classList.add('liked');
                    heartIcon.textContent = '❤️';
                } else {
                    this.classList.remove('liked');
                    heartIcon.textContent = '♡';
                }
                // 更新点赞数
                countSpan.textContent = data.likes_count;
            } else {
                alert(data.message);
            }
        })
        .catch(error => console.error('Error:', error));
    });
});
// 如果使用jQuery
$('.like-btn').on('click', function() {
    const contentId = $(this).data('content-id');
    const contentType = $(this).data('content-type');
    $.ajax({
        url: 'like.php',
        method: 'POST',
        data: {
            content_id: contentId,
            content_type: contentType
        },
        success: function(data) {
            if (data.success) {
                const $btn = $(this);
                $btn.toggleClass('liked');
                $btn.find('.likes-count').text(data.likes_count);
                if (data.liked) {
                    $btn.find('.heart-icon').text('❤️');
                } else {
                    $btn.find('.heart-icon').text('♡');
                }
            } else {
                alert(data.message);
            }
        },
        error: function() {
            alert('请求失败,请重试');
        }
    });
});

前端CSS样式

.like-btn {
    background: none;
    border: 1px solid #ddd;
    border-radius: 20px;
    padding: 5px 15px;
    cursor: pointer;
    transition: all 0.3s;
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
.like-btn:hover {
    background: #f0f0f0;
}
.like-btn.liked {
    color: #e74c3c;
    border-color: #e74c3c;
    background: #fde8e8;
}
.heart-icon {
    font-size: 18px;
}
.likes-count {
    font-size: 14px;
    font-weight: bold;
}

优化建议

缓存优化

// 使用Redis缓存点赞数
function getLikeCountCache($content_id, $content_type) {
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $key = "likes:{$content_type}:{$content_id}";
    $count = $redis->get($key);
    if ($count === false) {
        // 从数据库获取并缓存
        $dbCount = getLikesCountFromDB($content_id, $content_type);
        $redis->set($key, $dbCount, 3600); // 缓存1小时
        return $dbCount;
    }
    return $count;
}

防重复点击

let isLoading = false;
$('.like-btn').on('click', function() {
    if (isLoading) return;
    isLoading = true;
    // ... 请求代码 ...
    // 请求完成后
    isLoading = false;
});

完整示例代码

完整的实现还包括:

  • 用户登录状态检查
  • 点赞记录查询(页面加载时显示用户是否已点赞)
  • 点赞动画效果
  • 错误处理

如果需要完整的项目结构代码,我可以提供更详细的实现。

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