本文目录导读:

在PHP项目中实现资讯(文章/新闻)的置顶和推送功能,通常涉及数据库设计、业务逻辑处理和后端推送机制。
下面分别给出这两个功能的详细实现方案。
资讯置顶功能
置顶的核心逻辑是:根据一个排序字段,让置顶的资讯永远排在前面。
数据库设计
在 articles 表中增加两个字段:
is_top(TINYINT 1):是否置顶,0-否,1-是。top_order(INT 默认0):置顶排序权重,数字越大,排序越靠前(用于处理多条置顶文章的先后顺序)。
-- 示例表结构 CREATE TABLE `articles` ( `id` int(11) NOT NULL AUTO_INCREMENT, varchar(255) NOT NULL, `content` text, `created_at` datetime DEFAULT NULL, `is_top` tinyint(1) DEFAULT '0' COMMENT '是否置顶 0:否 1:是', `top_order` int(11) DEFAULT '0' COMMENT '置顶排序权重', PRIMARY KEY (`id`), KEY `idx_top` (`is_top`, `top_order`) -- 联合索引,加速排序查询 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
后台管理(设置置顶)
在管理后台的“资讯编辑”或“列表操作”中,提供一个“设为置顶”的操作。
PHP示例代码(设置置顶逻辑):
<?php // 假设接收到文章ID和置顶权重 $articleId = $_POST['article_id']; $topOrder = $_POST['top_order'] ?? 1; // 数字越大越靠前 // 1. 如果只想简单置顶(不分前后),设为1即可 // 2. 如果需要调整顺序,可以让管理员输入数字 $sql = "UPDATE articles SET is_top = 1, top_order = ? WHERE id = ?"; $stmt = $pdo->prepare($sql); $stmt->execute([$topOrder, $articleId]); // 可选:取消其他文章的置顶(如果只允许一条置顶) // $sql = "UPDATE articles SET is_top = 0 WHERE id != ?"; // $pdo->prepare($sql)->execute([$articleId]);
取消置顶:
$sql = "UPDATE articles SET is_top = 0, top_order = 0 WHERE id = ?"; $stmt = $pdo->prepare($sql); $stmt->execute([$articleId]);
前端列表查询(排序逻辑)
核心就是 ORDER BY 语句:先按置顶状态排序,再按置顶权重排序,最后按发布时间排序。
PHP示例代码(获取文章列表):
<?php
// 获取文章列表,置顶的永远在前
$sql = "SELECT * FROM articles
WHERE status = 1 -- 假设状态为已发布
ORDER BY
is_top DESC, -- 置顶的排前面 (1 > 0)
top_order DESC, -- 置顶的文章中,权重大的排前面
created_at DESC -- 非置顶的文章按时间倒序
LIMIT ? OFFSET ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$limit, $offset]);
$articles = $stmt->fetchAll();
优化建议:
- 如果数据量大,可以给
is_top, top_order, created_at加联合索引。 - 或者将置顶文章缓存到Redis,查询时先从Redis取置顶列表,再查数据库获取非置顶列表,然后合并。
资讯推送功能
推送是指:当资讯发布或更新时,主动通知用户,实现方式取决于你的应用类型(站内信、小程序、App等)。
这里介绍三种常见场景的实现:
站内信/消息推送(Web端)
适合用户登录网站后看到的“通知中心”。
- 数据表:
user_messages(user_id, article_id, type, is_read, created_at) - 流程:发布文章 -> 写入
user_messages表 -> 用户列表页查询。
<?php
// 发布文章成功后,推送站内信
function pushToAllUsers($articleId, $pdo) {
// 获取所有活跃用户的ID
$users = $pdo->query("SELECT id FROM users WHERE status = 1")->fetchAll();
// 批量插入消息(注意:用户量大时需分批,避免SQL过长)
$sql = "INSERT INTO user_messages (user_id, article_id, type, created_at) VALUES (?, ?, 'article_push', NOW())";
$stmt = $pdo->prepare($sql);
foreach ($users as $user) {
$stmt->execute([$user['id'], $articleId]);
}
// 如果是实时推送(WebSocket/SSE),这里可以触发通知
}
WebSocket 实时推送(一般配合 Laravel/PHP Swoole 等)
适合需要即时通知的场景(如后台管理系统、即时聊天)。
- 方案:使用 Laravel Echo + Pusher 或 Swoole WebSocket Server。
- 流程:
- 发布文章 -> PHP调用Redis发布订阅或直接发消息给WebSocket服务。
- WebSocket服务收到消息后,推送给连接到对应房间(如“所有用户”)的客户端。
简单示例(使用 Swoole):
// 1. 创建一个WebSocket服务(单独进程运行)
// 2. 在文章发布API中:
$redis->publish('news_push', json_encode(['article_id' => 123, 'title' => '新资讯']));
// 3. WebSocket Worker 订阅 Redis,收到消息后遍历所有连接并发送
第三方推送(App、小程序)
- App:集成极光推送、个推、小米推送等SDK,PHP后端调用其服务端API。
- 小程序:使用微信小程序订阅消息或统一服务消息。
- 邮件/短信:使用PHPMailer发送邮件,或调用阿里云/腾讯云的短信API。
示例(极光推送):
<?php
// 需要引入极光推送SDK
$client = new \JPush\Client('app_key', 'master_secret');
$push = $client->push();
$push->setPlatform('all')
->addAllAudience() // 推送给所有用户
->message('资讯标题', [
'extras' => ['article_id' => 123]
])
->send();
综合建议(完整流程)
假设你的项目是一个 资讯网站 + 微信公众号/小程序:
-
后台发布资讯:
- 、正文。
- 勾选“置顶”,并输入排序权重。
- 点击“发布并推送”。
-
后台PHP处理:
- 写入数据库
articles表 (is_top和top_order)。 - 调用 站内信 推送给所有用户(写入
user_messages)。 - 调用 极光推送 或 微信模板消息 推送到用户手机。
- 如果用户通过WebSocket在线,则实时推送。
- 写入数据库
-
前端展示:
- 列表页:按
ORDER BY is_top DESC, top_order DESC, created_at DESC排序。 - 置顶文章用特殊样式标记(如红色“置顶”标签)。
- 列表页:按
性能注意点
- 置顶:如果置顶文章经常变化,可以缓存置顶ID列表。
$topIds = $redis->zRevRange('top_articles', 0, -1); $normalArticles = $pdo->query("SELECT * FROM articles WHERE id NOT IN (".implode(',', $topIds).") ORDER BY created_at DESC LIMIT 20"); - 推送:
- 避免循环发送(如给10万用户发站内信),使用批量INSERT。
- 异步处理推送任务:将推送请求放入消息队列(Redis、RabbitMQ),后台Worker消费。
- 置顶:本质是 排序优先级,字段
is_top+top_order+ORDER BY即可解决。 - 推送:根据业务场景选型:
- 简单通知:站内信。
- 实时:WebSocket。
- 离线/移动:第三方推送服务。
如果你的项目已经是一个成熟的框架(如 Laravel、ThinkPHP),可以查看其事件系统(Events + Listeners)或队列(Queue),将推送逻辑解耦,提高响应速度。