本文目录导读:

我来详细介绍PHP信息流排序算法的实现方案:
基础排序算法实现
简单时间排序
<?php
class FeedSorter {
// 按时间倒序排列
public function sortByTime(array $feeds): array {
usort($feeds, function($a, $b) {
return strtotime($b['created_at']) - strtotime($a['created_at']);
});
return $feeds;
}
}
?>
热度加权排序(Hacker News算法)
<?php
class HackerNewsRanker {
/**
* Hacker News 热度算法
* Score = (P-1) / (T+2)^G
* P = 点赞数,T = 发布时间(小时),G = 重力因子(通常1.8)
*/
public function calculateScore(int $points, int $hoursAgo, float $gravity = 1.8): float {
if ($points <= 0) return 0;
return ($points - 1) / pow(($hoursAgo + 2), $gravity);
}
public function sortByHackerNews(array $feeds): array {
$now = time();
foreach ($feeds as &$feed) {
$hoursAgo = ($now - strtotime($feed['created_at'])) / 3600;
$feed['score'] = $this->calculateScore(
$feed['likes'] ?? 0,
$hoursAgo
);
}
usort($feeds, function($a, $b) {
return $b['score'] <=> $a['score'];
});
return $feeds;
}
}
?>
Reddit热门排序算法
<?php
class RedditRanker {
/**
* Reddit 热门排序
* Score = log10(max(ups, 1)) + sign(ups-downs) * seconds/45000
*/
public function hotScore(int $ups, int $downs, string $createdAt): float {
$seconds = max(1, strtotime($createdAt) - 1134028003);
$score = log10(max($ups, 1)) + ($ups - $downs) * $seconds / 45000;
return $score;
}
public function sortByHot(array $feeds): array {
foreach ($feeds as &$feed) {
$ups = $feed['likes'] ?? 0;
$downs = $feed['dislikes'] ?? 0;
$feed['score'] = $this->hotScore($ups, $downs, $feed['created_at']);
}
usort($feeds, function($a, $b) {
return $b['score'] <=> $a['score'];
});
return $feeds;
}
}
?>
综合权重排序算法
<?php
class ComprehensiveRanker {
private $weights = [
'time' => 0.4,
'likes' => 0.3,
'comments' => 0.2,
'shares' => 0.1
];
// 配置权重
public function setWeights(array $weights): void {
$this->weights = array_merge($this->weights, $weights);
}
/**
* 计算综合得分
*/
public function calculateScore(array $feed): float {
// 时间衰减因子(48小时衰减)
$timeScore = $this->timeDecay($feed['created_at'], 48);
// 互动得分归一化
$likeScore = $this->normalize($feed['likes'] ?? 0);
$commentScore = $this->normalize($feed['comments'] ?? 0);
$shareScore = $this->normalize($feed['shares'] ?? 0);
return (
$this->weights['time'] * $timeScore +
$this->weights['likes'] * $likeScore +
$this->weights['comments'] * $commentScore +
$this->weights['shares'] * $shareScore
);
}
// 时间衰减函数(指数衰减)
private function timeDecay(string $timestamp, int $halfLifeHours): float {
$ageHours = (time() - strtotime($timestamp)) / 3600;
return pow(0.5, $ageHours / $halfLifeHours);
}
// 归一化(对数归一化)
private function normalize(int $value): float {
if ($value <= 0) return 0;
return log10($value + 1) / log10(10001); // 上限10000
}
public function sortFeeds(array $feeds): array {
foreach ($feeds as &$feed) {
$feed['score'] = $this->calculateScore($feed);
}
usort($feeds, function($a, $b) {
return $b['score'] <=> $a['score'];
});
return $feeds;
}
}
?>
基于用户偏好的个性化排序
<?php
class PersonalizedRanker {
private $userInterests = [];
private $userHistory = [];
public function __construct(array $userInterests, array $userHistory) {
$this->userInterests = $userInterests; // 兴趣标签权重
$this->userHistory = $userHistory; // 历史互动记录
}
/**
* 个性化推荐排序
*/
public function personalizedScore(array $feed): float {
$baseScore = 0;
$interestScore = 0;
$historyScore = 0;
// 1. 内容标签匹配度
if (isset($feed['tags'])) {
foreach ($feed['tags'] as $tag) {
if (isset($this->userInterests[$tag])) {
$interestScore += $this->userInterests[$tag];
}
}
}
// 2. 历史行为偏好
if (isset($this->userHistory[$feed['author_id']])) {
$historyScore = $this->userHistory[$feed['author_id']] * 0.1;
}
// 3. 内容质量分(结合其他算法)
$qualityScore = $this->calculateQualityScore($feed);
// 综合计算
$baseScore = $interestScore * 0.5 + $historyScore * 0.2 + $qualityScore * 0.3;
return $baseScore;
}
private function calculateQualityScore(array $feed): float {
// 结合时间衰减和互动量
$timeFactor = $this->timeDecay($feed['created_at']);
$interactionFactor = log10(($feed['likes'] ?? 0) + ($feed['comments'] ?? 0) + 1);
return $timeFactor * $interactionFactor;
}
private function timeDecay(string $timestamp): float {
$hours = (time() - strtotime($timestamp)) / 3600;
return 1 / (1 + $hours * 0.01);
}
}
?>
分页与性能优化
<?php
class FeedPaginator {
/**
* 游标分页(比传统页码分页更高效)
*/
public function getFeedsWithCursor(PDO $pdo, ?string $cursor, int $limit = 20): array {
$sql = "SELECT * FROM feeds ";
if ($cursor) {
// 游标包含时间戳和ID
[$cursorTime, $cursorId] = explode('_', $cursor);
$sql .= "WHERE (created_at < :time) OR (created_at = :time AND id < :id) ";
}
$sql .= "ORDER BY created_at DESC, id DESC LIMIT :limit";
$stmt = $pdo->prepare($sql);
if ($cursor) {
$stmt->bindValue(':time', $cursorTime);
$stmt->bindValue(':id', $cursorId);
}
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
$feeds = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 生成下一次的游标
$nextCursor = null;
if (count($feeds) == $limit) {
$last = end($feeds);
$nextCursor = $last['created_at'] . '_' . $last['id'];
}
return [
'feeds' => $feeds,
'next_cursor' => $nextCursor
];
}
}
?>
缓存策略
<?php
class FeedCacheManager {
private $redis;
public function __construct(Redis $redis) {
$this->redis = $redis;
}
/**
* 缓存热门feed列表
*/
public function cacheHotFeeds(array $feeds, int $ttl = 300): void {
$key = 'feed:hot:' . date('YmdH');
$this->redis->setex($key, $ttl, json_encode($feeds));
}
/**
* 增量更新排序(新feed插入时维护排序列表)
*/
public function addFeedToSortedSet(string $feedId, float $score): void {
$key = 'feed:scores:day:' . date('Ymd');
$this->redis->zadd($key, $score, $feedId);
// 保留前1000条
$this->redis->zremrangebyrank($key, 0, -1001);
}
/**
* 获取排序后的feed ID列表
*/
public function getTopFeeds(int $limit = 20): array {
$key = 'feed:scores:day:' . date('Ymd');
return $this->redis->zrevrange($key, 0, $limit - 1);
}
}
?>
完整示例
<?php
// 集成示例
class FeedService {
private $ranker;
private $cache;
public function __construct() {
// 配置权重
$this->ranker = new ComprehensiveRanker();
$this->ranker->setWeights([
'time' => 0.35,
'likes' => 0.25,
'comments' => 0.25,
'shares' => 0.15
]);
}
public function getFeedList(int $userId, int $page = 1, int $limit = 20): array {
// 获取原始feed
$feeds = $this->fetchFeedsFromDB($page, $limit);
// 个性化排序
$userInterests = $this->getUserInterests($userId);
$userHistory = $this->getUserHistory($userId);
$personalRanker = new PersonalizedRanker($userInterests, $userHistory);
foreach ($feeds as &$feed) {
// 综合排序 + 个性化加权
$feed['score'] = $this->ranker->calculateScore($feed) * 0.7 +
$personalRanker->personalizedScore($feed) * 0.3;
}
// 排序和分页
usort($feeds, function($a, $b) {
if ($b['score'] == $a['score']) {
return strtotime($b['created_at']) <=> strtotime($a['created_at']);
}
return $b['score'] <=> $a['score'];
});
return array_slice($feeds, ($page - 1) * $limit, $limit);
}
}
?>
算法选择建议
- 小型社区:简单时间排序足够型平台**:Reddit/Hacker News算法较合适
- 社交平台:需要个性化排序
- 商业场景:综合权重算法更佳
选择时要考虑业务目标、用户规模、内容特性和性能要求。