溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

php如何實現點贊取消功能

發布時間:2021-07-19 10:09:12 來源:億速云 閱讀:208 作者:chen 欄目:編程語言
# PHP如何實現點贊取消功能

## 目錄
1. [功能需求分析](#功能需求分析)
2. [數據庫設計](#數據庫設計)
3. [前端交互實現](#前端交互實現)
4. [后端邏輯處理](#后端邏輯處理)
   - [4.1 點贊功能實現](#41-點贊功能實現)
   - [4.2 取消點贊實現](#42-取消點贊實現)
5. [性能優化方案](#性能優化方案)
6. [安全防護措施](#安全防護措施)
7. [完整代碼示例](#完整代碼示例)
8. [擴展功能建議](#擴展功能建議)

## 功能需求分析

點贊/取消點贊是社交類網站的基礎功能,需要滿足以下核心需求:

1. 用戶可對內容(文章/視頻/評論)進行點贊
2. 已點贊用戶可取消操作
3. 實時顯示點贊數量變化
4. 防止重復點贊和惡意刷贊
5. 區分已點贊/未點贊狀態(UI反饋)

技術實現要點:
- 前端通過AJAX實現無刷新交互
- 后端使用PHP+MySQL處理數據
- 需要用戶認證系統支持

## 數據庫設計

### 方案一:計數器+關系表
```sql
-- 內容主表(示例)
CREATE TABLE `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `content` text NOT NULL,
  `like_count` int(11) DEFAULT 0,
  PRIMARY KEY (`id`)
);

-- 點贊關系表
CREATE TABLE `user_likes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `post_id` int(11) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `user_post` (`user_id`,`post_id`)
);

方案二:純關系表統計

-- 不維護計數器,每次實時統計
CREATE TABLE `user_likes` (
  `user_id` int(11) NOT NULL,
  `post_id` int(11) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`user_id`,`post_id`)
);

兩種方案對比:

方案 寫入性能 讀取性能 數據一致性
計數器+關系表 較高(需事務) 極高 需要維護
純關系表 極高 較低(需COUNT) 自動保證

前端交互實現

HTML結構示例

<div class="post" data-post-id="123">
  <h2>文章標題</h2>
  <div class="like-area">
    <button class="like-btn <?= $hasLiked ? 'active' : '' ?>">
      <i class="icon-thumbs-up"></i>
      <span class="like-count"><?= $likeCount ?></span>
    </button>
  </div>
</div>

JavaScript處理

document.querySelectorAll('.like-btn').forEach(btn => {
  btn.addEventListener('click', async function() {
    const postId = this.closest('.post').dataset.postId;
    const isActive = this.classList.contains('active');
    
    try {
      const response = await fetch('/like.php', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          post_id: postId,
          action: isActive ? 'unlike' : 'like'
        })
      });
      
      const result = await response.json();
      
      if (result.success) {
        this.classList.toggle('active');
        this.querySelector('.like-count').textContent = result.like_count;
      }
    } catch (error) {
      console.error('操作失敗:', error);
    }
  });
});

后端邏輯處理

4.1 點贊功能實現

// like.php
require 'db_connect.php';
session_start();

if (!isset($_SESSION['user_id'])) {
  http_response_code(401);
  die(json_encode(['error' => '請先登錄']));
}

$input = json_decode(file_get_contents('php://input'), true);
$postId = intval($input['post_id'] ?? 0);
$action = $input['action'] === 'unlike' ? 'unlike' : 'like';

// 開啟事務
$pdo->beginTransaction();

try {
  if ($action === 'like') {
    // 檢查是否已點贊
    $stmt = $pdo->prepare("SELECT 1 FROM user_likes WHERE user_id = ? AND post_id = ?");
    $stmt->execute([$_SESSION['user_id'], $postId]);
    
    if ($stmt->fetch()) {
      throw new Exception('您已經點過贊了');
    }
    
    // 插入點贊記錄
    $pdo->prepare("INSERT INTO user_likes (user_id, post_id) VALUES (?, ?)")
      ->execute([$_SESSION['user_id'], $postId]);
    
    // 更新計數器
    $pdo->prepare("UPDATE posts SET like_count = like_count + 1 WHERE id = ?")
      ->execute([$postId]);
  } else {
    // 取消點贊邏輯...
  }
  
  // 獲取最新點贊數
  $likeCount = $pdo->query("SELECT like_count FROM posts WHERE id = $postId")
    ->fetchColumn();
  
  $pdo->commit();
  
  echo json_encode([
    'success' => true,
    'like_count' => $likeCount
  ]);
} catch (Exception $e) {
  $pdo->rollBack();
  http_response_code(400);
  echo json_encode(['error' => $e->getMessage()]);
}

4.2 取消點贊實現

// 接續上面的try塊中的else分支
} else {
  // 檢查是否有點贊記錄
  $stmt = $pdo->prepare("SELECT 1 FROM user_likes WHERE user_id = ? AND post_id = ?");
  $stmt->execute([$_SESSION['user_id'], $postId]);
  
  if (!$stmt->fetch()) {
    throw new Exception('您尚未點贊');
  }
  
  // 刪除點贊記錄
  $pdo->prepare("DELETE FROM user_likes WHERE user_id = ? AND post_id = ?")
    ->execute([$_SESSION['user_id'], $postId]);
  
  // 更新計數器
  $pdo->prepare("UPDATE posts SET like_count = GREATEST(0, like_count - 1) WHERE id = ?")
    ->execute([$postId]);
}

性能優化方案

  1. 緩存策略: “`php // 使用Redis緩存熱門文章的點贊數 \(redis = new Redis(); \)redis->connect(‘127.0.0.1’, 6379);

\(cacheKey = "post:{\)postId}:likes”;

// 寫入時更新緩存 \(redis->set(\)cacheKey, $likeCount, 3600);

// 讀取時優先查緩存 \(likeCount = \)redis->get(\(cacheKey); if (\)likeCount === false) { \(likeCount = \)pdo->query(“SELECT like_count…”)->fetchColumn(); \(redis->set(\)cacheKey, $likeCount, 3600); }


2. **批量查詢優化**:
   ```sql
   -- 一次查詢獲取用戶是否點贊過多個文章
   SELECT post_id FROM user_likes 
   WHERE user_id = ? AND post_id IN (1, 2, 3, 4);
  1. 延遲更新
    
    // 對于高流量場景,可采用隊列異步更新
    $queue->push([
     'type' => 'like',
     'user_id' => $userId,
     'post_id' => $postId,
     'action' => $action
    ]);
    

安全防護措施

  1. CSRF防護

    <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
    
  2. 頻率限制: “`php \(redis->incr("user:{\)_SESSION[‘user_id’]}:like_attempts”); \(redis->expire("user:{\)_SESSION[‘user_id’]}:like_attempts”, 60);

if ($redis->get() > 30) { http_response_code(429); die(‘操作過于頻繁’); }


3. **輸入驗證增強**:
   ```php
   if (!ctype_digit($postId) {
     die('非法參數');
   }
   
   // 檢查文章是否存在
   $stmt = $pdo->prepare("SELECT 1 FROM posts WHERE id = ?");
   $stmt->execute([$postId]);
   if (!$stmt->fetch()) {
     die('內容不存在');
   }

完整代碼示例

數據庫連接 (db_connect.php)

<?php
$host = 'localhost';
$dbname = 'your_database';
$user = 'db_user';
$pass = 'db_password';

try {
  $pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
  die("數據庫連接失敗: " . $e->getMessage());
}

前端完整示例 (index.php)

<?php
session_start();
require 'db_connect.php';

// 獲取文章列表
$posts = $pdo->query("SELECT id, title, content, like_count FROM posts")->fetchAll();

// 檢查用戶點贊狀態
$userLikes = [];
if (isset($_SESSION['user_id'])) {
  $stmt = $pdo->prepare("SELECT post_id FROM user_likes WHERE user_id = ?");
  $stmt->execute([$_SESSION['user_id']]);
  $userLikes = $stmt->fetchAll(PDO::FETCH_COLUMN);
}
?>
<!DOCTYPE html>
<html>
<!-- 頭部內容... -->
<body>
  <?php foreach ($posts as $post): ?>
    <div class="post" data-post-id="<?= $post['id'] ?>">
      <h2><?= htmlspecialchars($post['title']) ?></h2>
      <p><?= nl2br(htmlspecialchars($post['content'])) ?></p>
      <button class="like-btn <?= in_array($post['id'], $userLikes) ? 'active' : '' ?>">
        <i class="icon-thumbs-up"></i>
        <span class="like-count"><?= $post['like_count'] ?></span>
      </button>
    </div>
  <?php endforeach; ?>
  
  <script src="like.js"></script>
</body>
</html>

擴展功能建議

  1. 點贊通知系統

    // 在點贊成功后
    if ($action === 'like') {
     $stmt = $pdo->prepare("INSERT INTO notifications 
       (user_id, type, content_id, sender_id) 
       VALUES (?, 'like', ?, ?)");
     $authorId = $pdo->query("SELECT user_id FROM posts WHERE id = $postId")
       ->fetchColumn();
     $stmt->execute([$authorId, $postId, $_SESSION['user_id']]);
    }
    
  2. 點贊排行榜

    SELECT posts.*, COUNT(user_likes.id) as like_count
    FROM posts
    LEFT JOIN user_likes ON posts.id = user_likes.post_id
    GROUP BY posts.id
    ORDER BY like_count DESC
    LIMIT 10
    
  3. 點贊動畫效果

    btn.classList.add('animate');
    setTimeout(() => {
     btn.classList.remove('animate'); 
    }, 1000);
    
  4. 多類型內容支持

    ALTER TABLE user_likes ADD COLUMN content_type ENUM('post','comment','video') NOT NULL;
    

通過以上實現,我們完成了一個健壯的點贊/取消點贊系統。實際項目中可根據具體需求進行調整和擴展。 “`

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

php
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女