PHP项目怎样实现内容随机推荐?

wen PHP项目 52

本文目录导读:

PHP项目怎样实现内容随机推荐?

  1. 数据库随机查询(最简单)
  2. 基于时间戳的伪随机
  3. 缓存推荐列表(高性能方案)
  4. 加权随机推荐(推荐算法)
  5. 基于用户行为的推荐(协同过滤)
  6. 前端随机展示(无后端请求)
  7. 性能优化建议
  8. 完整示例:混合推荐策略

在PHP项目中实现内容随机推荐,有多种方法,从简单到复杂,适合不同的应用场景,以下是几种主流方案:

数据库随机查询(最简单)

MySQL随机获取

// 方法一:RAND()函数(数据量小推荐)
$sql = "SELECT * FROM articles ORDER BY RAND() LIMIT 5";
$result = mysqli_query($conn, $sql);
// 方法二:子查询优化(数据量大时)
$sql = "SELECT * FROM articles 
        WHERE id >= (
            SELECT FLOOR(RAND() * (SELECT MAX(id) FROM articles))
        ) 
        LIMIT 5";

PostgreSQL随机获取

// PostgreSQL使用RANDOM()
$sql = "SELECT * FROM articles ORDER BY RANDOM() LIMIT 5";

注意ORDER BY RAND()在数据量大时性能很差,会全表扫描。

基于时间戳的伪随机

function getRandomArticles($db, $limit = 5) {
    // 使用当前时间戳作为种子,每天变化一次
    $seed = date('Ymd');
    mt_srand($seed);
    // 获取总文章数
    $count_result = mysqli_query($db, "SELECT COUNT(*) FROM articles");
    $total = mysqli_fetch_array($count_result)[0];
    // 生成随机ID集合
    $ids = [];
    for ($i = 0; $i < $limit; $i++) {
        $ids[] = mt_rand(1, $total);
    }
    // 查询这些ID的文章
    $ids_str = implode(',', $ids);
    $sql = "SELECT * FROM articles WHERE id IN ($ids_str)";
    return mysqli_query($db, $sql);
}

缓存推荐列表(高性能方案)

class RandomRecommendation {
    private $cacheFile = 'random_cache.json';
    private $cacheExpire = 3600; // 1小时更新一次
    public function getRecommendations($count = 5) {
        // 检查缓存
        if (file_exists($this->cacheFile) && 
            time() - filemtime($this->cacheFile) < $this->cacheExpire) {
            $data = json_decode(file_get_contents($this->cacheFile), true);
            return $this->pickRandom($data, $count);
        }
        return $this->refreshCache($count);
    }
    private function refreshCache($count) {
        // 从数据库获取所有推荐内容
        $db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
        $stmt = $db->query("SELECT id, title, url FROM articles");
        $articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
        // 保存到缓存
        file_put_contents($this->cacheFile, json_encode($articles));
        return $this->pickRandom($articles, $count);
    }
    private function pickRandom($data, $count) {
        shuffle($data);
        return array_slice($data, 0, $count);
    }
}

加权随机推荐(推荐算法)

class WeightedRandomRecommendation {
    public function getRecommendations($userId, $count = 5) {
        $db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
        // 获取用户兴趣标签权重
        $stmt = $db->prepare("
            SELECT category, weight 
            FROM user_interests 
            WHERE user_id = ?
        ");
        $stmt->execute([$userId]);
        $interests = $stmt->fetchAll(PDO::FETCH_ASSOC);
        // 如果没有兴趣标签,使用纯随机
        if (empty($interests)) {
            return $this->randomArticles($db, $count);
        }
        // 构建加权查询
        $cases = [];
        foreach ($interests as $interest) {
            $cases[] = "WHEN category = '{$interest['category']}' THEN {$interest['weight']}";
        }
        $caseSql = implode(' ', $cases);
        $sql = "
            SELECT *,
            CASE 
                $caseSql
                ELSE 1 
            END as weight
            FROM articles 
            ORDER BY RAND() * weight DESC 
            LIMIT $count
        ";
        return $db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
    }
}

基于用户行为的推荐(协同过滤)

class CollaborativeFiltering {
    public function recommendForUser($userId, $limit = 5) {
        $db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
        // 1. 找到相似用户(使用简单的Jaccard相似度)
        $similarUsers = $this->findSimilarUsers($db, $userId);
        // 2. 获取相似用户喜欢的文章
        $stmt = $db->prepare("
            SELECT a.*, COUNT(*) as score
            FROM articles a
            JOIN user_actions ua ON a.id = ua.article_id
            WHERE ua.user_id IN (".implode(',', $similarUsers).")
            AND a.id NOT IN (
                SELECT article_id FROM user_actions WHERE user_id = ?
            )
            GROUP BY a.id
            ORDER BY score DESC, RAND()
            LIMIT ?
        ");
        $stmt->execute([$userId, $limit]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    private function findSimilarUsers($db, $userId) {
        // 简化实现:找相同兴趣的人
        $stmt = $db->prepare("
            SELECT ua2.user_id
            FROM user_actions ua1
            JOIN user_actions ua2 ON ua1.article_id = ua2.article_id
            WHERE ua1.user_id = ? 
            AND ua2.user_id != ?
            GROUP BY ua2.user_id
            HAVING COUNT(*) >= 3
            LIMIT 10
        ");
        $stmt->execute([$userId, $userId]);
        return $stmt->fetchAll(PDO::FETCH_COLUMN);
    }
}

前端随机展示(无后端请求)

<!DOCTYPE html>
<html>
<head>
    <script>
    var articles = <?php
        $db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
        $articles = $db->query("SELECT id, title, url FROM articles")->fetchAll(PDO::FETCH_ASSOC);
        echo json_encode($articles);
    ?>;
    function getRandomRecommendations(count) {
        var shuffled = [...articles];
        for (let i = shuffled.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
        }
        return shuffled.slice(0, count);
    }
    // 使用
    var recommendations = getRandomRecommendations(5);
    </script>
</head>
</html>

性能优化建议

  1. 数据量大时:不要使用ORDER BY RAND()
  2. 使用缓存:Redis/Memcached缓存推荐列表
  3. 预生成:定时脚本生成推荐列表
  4. 分而治之:按分类/标签分别存储

完整示例:混合推荐策略

class SmartRecommendation {
    public function getRecommendations($userId, $count = 5) {
        $recommendations = [];
        // 策略1: 70%概率从用户兴趣中推荐
        if (rand(1, 100) <= 70 && $userId) {
            $recommendations = $this->interestBasedRecommend($userId, $count);
        }
        // 策略2: 补充随机推荐
        if (count($recommendations) < $count) {
            $remain = $count - count($recommendations);
            $random = $this->randomRecommend($remain);
            $recommendations = array_merge($recommendations, $random);
        }
        // 去重并打乱
        $recommendations = array_unique($recommendations, SORT_REGULAR);
        shuffle($recommendations);
        return array_slice($recommendations, 0, $count);
    }
}

选择建议

  • 小型网站:使用ORDER BY RAND()最省事
  • 中型网站:缓存+预生成推荐列表
  • 大型网站:使用Redis缓存 + 定时任务生成推荐
  • 个性化需求:基于用户行为的推荐算法

哪种方案最适合你的项目?告诉我具体的访问量和数据规模,我可以帮你选择合适的方案。

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