php
复制代码
<?php
// 1. 查询用户最近交互过的文章相关作者(点赞/评论记录)
use app\common\service\HelperService;
use think\facade\Db;
// 初始化变量
$interacted_authors = [];
// 用户参数设置
$user_id = 1; // 当前用户ID
$page_type = 0; // 推荐页面类型
$filter_conditions = []; // 查询过滤条件
$page_number = input('page', 1); // 页码
$page_size = input('limit', 10); // 每页记录数
$random_seed = '11'; // 随机数种子,用于随机推荐的一致性
// 当访问第一页时,重置用户阅读记录
if ($page_number == 1) {
// 清除该用户在此类型页面的阅读记录
Db::name('user_article_read_log')->where('type', $page_type)->where('user_id', $user_id)->delete();
}
// 获取用户最近点赞过的文章作者
$liked_authors = Db::name('articles_like')
->alias('al')
->join('articles a', 'a.id = al.article_id')
->where('al.user_id', $user_id)
->where($filter_conditions)
->whereTime('al.create_time', '-30 days') // 最近30天内
->column('a.user_id');
// 获取用户最近评论过的文章作者
$commented_authors = DB::name('articles_comment')
->alias('ac')
->join('articles a', 'a.id = ac.article_id')
->where($filter_conditions)
->where('ac.user_id', $user_id)
->whereTime('ac.create_time', '-30 days') // 最近30天内
->column('a.user_id');
// 合并并去重用户交互过的作者ID
$interacted_authors = HelperService::arrayFilterUnique(array_merge($liked_authors, $commented_authors));
// 2. 构建推荐查询 - 使用子查询和UNION方式组合多种推荐策略
// 策略1: 获取热门文章(高点赞、高评论)- 占50%权重
$hot_article_limit = ceil($page_size * 0.5);
$hot_article_query = DB::name('articles')
->alias('a')
->join('user_article_read_log rl', 'rl.article_id = a.id and rl.user_id='.$user_id, 'left')
->where('a.status', 1)
->whereNull('rl.id') // 排除已阅读的文章
->where($filter_conditions)
->where('a.create_time', '>', time() - 7 * 24 * 3600) // 最近7天内
->order('a.like_count DESC, a.comment_count DESC, a.create_time DESC')
->field('a.*')
->limit($hot_article_limit)
->buildSql();
// 策略2: 如果用户有交互历史,则获取相关作者的最新文章 - 占30%权重
$related_article_query = '';
$related_article_limit = ceil($page_size * 0.3);
if (!empty($interacted_authors)) {
$related_article_query = DB::name('articles')
->alias('a')
->join('user_article_read_log rl', 'rl.article_id = a.id and rl.user_id='.$user_id, 'left')
->where($filter_conditions)
->whereNull('rl.id') // 排除已阅读的文章
->where('a.status', 1)
->whereIn('a.user_id', $interacted_authors)
->whereTime('a.create_time', '-15 days') // 最近15天
->order('a.create_time DESC')
->limit($related_article_limit)
->field('a.*')
->buildSql();
}
// 策略3: 随机推荐文章以增加多样性 - 占20%权重或在无交互历史时占50%
$random_article_limit = empty($interacted_authors) ? ceil($page_size * 0.5) : ceil($page_size * 0.2);
$random_article_base_query = DB::name('articles')
->alias('a')
->join('user_article_read_log rl', 'rl.article_id = a.id and rl.user_id='.$user_id, 'left')
->whereNull('rl.id') // 排除已阅读的文章
->where($filter_conditions)
->where('a.status', 1)
->whereTime('a.create_time', '-30 days') // 最近30天
->orderRaw('RAND('.$random_seed.')')
->field('a.*');
// 构建随机文章的SQL
$random_article_sql = $random_article_base_query->limit($random_article_limit)->buildSql();
// 组合所有查询
$union_queries = array_filter([$hot_article_query, $related_article_query, $random_article_sql]);
$combined_sql = implode(' UNION ', $union_queries);
$combined_sql = '(' . $combined_sql . ')';
// 执行合并查询
$recommended_articles = Db::table($combined_sql . ' a')
->select()->toArray();
// 如果推荐结果不足,补充随机文章
if (count($recommended_articles) < $page_size) {
$additional_articles = $random_article_base_query
->whereNotIn('a.id', array_column($recommended_articles, 'id'))
->limit($page_size - count($recommended_articles))
->select()
->toArray();
$recommended_articles = array_values(array_filter(array_merge(
$recommended_articles ?: [],
$additional_articles ?: []
)));
}
// 设置返回数据
$article_list = $recommended_articles;
$total_count = Db::name('articles')->count();
// 记录用户阅读日志,用于下次推荐时排除已读内容
$read_logs = [];
foreach ($article_list as $article) {
$read_logs[] = [
'user_id' => $user_id,
'article_id' => $article['id'],
'type' => $page_type
];
}
// 批量插入阅读记录
if (!empty($read_logs)) {
Db::name('user_article_read_log')->insertAll($read_logs);
}