仿我喜欢网站源码免费,动易网站建设工作室,中文 wordpress插件下载,济南网站建设加q479185700以下将详细介绍当歌平台的技术架构、功能实现以及相关代码逻辑。 一、项目概述
当歌是一个极简的 RSS 订阅分发平台#xff0c;旨在为用户提供便捷的 RSS 管理和订阅服务#xff0c;帮助用户轻松获取和分享最新资讯。
二、技术架构
后端语言#xff1a;PHP 数据库#… 以下将详细介绍当歌平台的技术架构、功能实现以及相关代码逻辑。 一、项目概述
当歌是一个极简的 RSS 订阅分发平台旨在为用户提供便捷的 RSS 管理和订阅服务帮助用户轻松获取和分享最新资讯。
二、技术架构
后端语言PHP 数据库MySQL通过 PDOPHP Data Objects进行连接和操作配置信息如下
$host localhost;
$db rss;
$user rss;
$pass 123456;
$charset utf8mb4;
$dsn mysql:host$host;dbname$db;charset$charset;
$options [PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE PDO::FETCH_ASSOC,PDO::ATTR_EMULATE_PREPARES false,
];
try {$pdo new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {throw new \PDOException($e-getMessage(), (int)$e-getCode());
}**邮件发送**使用 PHPMailer 库来实现邮件发送功能用于发送验证码和订阅推送邮件。
三、功能模块
一用户认证与登录
在 index.php、add_rss.php 等多个页面中通过 session_start() 启动会话并检查 $_SESSION[username] 是否存在来判断用户是否登录。例如在 index.php 中
session_start();
$isLoggedIn isset($_SESSION[username]);如果用户已登录导航栏会显示用户名及退出登录选项未登录时则显示登录和注册链接。
二订阅管理
添加订阅 在 add_rss.php 中首先获取用户 ID若用户未登录则提示先登录。然后检查用户是否已有密钥若无则生成一个新的密钥并存储到 user_keys 表中。 当用户提交 RSS URL 时会检查是否已订阅该 URL若未订阅且 URL 可访问则将订阅信息插入到 subscriptions 表中并触发 update_rss.php 进行 RSS 内容更新。 部分关键代码如下
// 获取用户ID
$stmt $pdo-prepare(SELECT id FROM users WHERE username ?);
$stmt-execute([$username]);
$user $stmt-fetch();
$userId $user[id];// 检查用户是否已有密钥
$stmt $pdo-prepare(SELECT user_key FROM user_keys WHERE user_id ?);
$stmt-execute([$userId]);
$userKey $stmt-fetchColumn();
if (!$userKey) {// 生成新密钥并插入$userKey bin2hex(random_bytes(16));$stmt $pdo-prepare(INSERT INTO user_keys (user_id, user_key) VALUES (?,?));$stmt-execute([$userId, $userKey]);
}// 处理添加订阅请求
if ($_SERVER[REQUEST_METHOD] POST isset($_POST[rss_url])) {$rssUrl $_POST[rss_url]?? ;if ($rssUrl $userId) {// 检查是否已订阅$stmt $pdo-prepare(SELECT COUNT(*) FROM subscriptions WHERE user_id ? AND rss_url ?);$stmt-execute([$userId, $rssUrl]);$count $stmt-fetchColumn();if ($count 0) {echo div classalert alert-warning您已订阅此 RSS 源/div;} else {// 验证 RSS URL 是否可访问$rss simplexml_load_file($rssUrl);if ($rss) {// 添加订阅关系$stmt $pdo-prepare(INSERT INTO subscriptions (user_id, rss_url) VALUES (?,?));$stmt-execute([$userId, $rssUrl]);// 触发更新$updateUrl https://dang.ge/update_rss.php?key{$userKey};$response file_get_contents($updateUrl);if ($response FALSE) {echo div classalert alert-danger无法调用更新服务请检查配置。/div;} else {echo div classalert alert-success订阅添加成功并已更新。/div;}// 刷新页面header(Location: add_rss.php);exit;} else {echo div classalert alert-danger无法访问该 RSS 源请检查 URL 是否正确/div;}}}
}删除订阅 当用户提交要删除的 RSS URL 时会从 subscriptions 表和 rss_items 表中删除相关记录并刷新页面以反映删除操作。 代码示例
if ($_SERVER[REQUEST_METHOD] POST isset($_POST[delete_rss_url])) {$rssUrlToDelete $_POST[delete_rss_url]?? ;if ($rssUrlToDelete $userId) {$stmt $pdo-prepare(DELETE FROM subscriptions WHERE user_id ? AND rss_url ?);$stmt-execute([$userId, $rssUrlToDelete]);// 删除相关 RSS 内容$stmt $pdo-prepare(DELETE FROM rss_items WHERE user_id ? AND rss_url ?);$stmt-execute([$userId, $rssUrlToDelete]);// 刷新页面header(Location: add_rss.php);exit;}
}订阅列表展示 从 subscriptions 表中获取用户的订阅信息并在页面上以列表形式展示每个订阅项包含订阅源标题和删除按钮。点击订阅源标题可查看该订阅的内容。 相关代码如下
// 获取订阅信息
$stmt $pdo-prepare(SELECT rss_url FROM subscriptions WHERE user_id ?);
$stmt-execute([$userId]);
$subscriptions $stmt-fetchAll();// 展示订阅列表
foreach ($subscriptions as $subscription) {$rssUrl $subscription[rss_url];$rss simplexml_load_file($rssUrl);$channelTitle $rss-channel-title?? $rss-title?? 未知标题;?li classlist-group-item d-flex justify-content-between align-items-centerform methodpost action classd-inlineinput typehidden nameselected_rss value?php echo htmlspecialchars($rssUrl);?button typesubmit classbtn btn-link p-0?php echo htmlspecialchars($channelTitle);?/button/formform methodpost action classd-inlineinput typehidden namedelete_rss_url value?php echo htmlspecialchars($rssUrl);?button typesubmit classbtn btn-danger btn-sm删除/button/form/li?php
}三RSS 内容更新与推送
更新机制 在 update_rss.php 中根据用户密钥获取用户 ID然后获取用户的所有订阅 RSS URL。对于每个 URL先加载 RSS 内容检测其格式Atom 或其他并获取条目。 接着获取已存在的链接对比新条目链接若不存在则插入到 rss_items 表中并构建邮件内容。 关键代码如下
$key $_GET[key]?? null;
if (!$key) {echo 无效的请求;exit;
}
// 验证密钥
$stmt $pdo-prepare(SELECT user_id FROM user_keys WHERE user_key ?);
$stmt-execute([$key]);
$userKey $stmt-fetch();
if (!$userKey) {echo 无效的密钥;exit;
}
$userId $userKey[user_id];// 获取用户的订阅
$stmt $pdo-prepare(SELECT DISTINCT rss_url FROM subscriptions WHERE user_id ?);
$stmt-execute([$userId]);
$rssUrls $stmt-fetchAll();foreach ($rssUrls as $rssUrl) {$url $rssUrl[rss_url];$rss simplexml_load_file($url);if ($rss) {// 检测格式并获取条目$isAtom $rss-getNamespaces(true)[] http://www.w3.org/2005/Atom;$items $isAtom? ($rss-entry?? []) : ($rss-channel-item?? []);// 获取已存在链接$stmt $pdo-prepare(SELECT link FROM rss_items WHERE user_id ? AND rss_url ?);$stmt-execute([$userId, $url]);$existingLinks $stmt-fetchAll(PDO::FETCH_COLUMN);$newCount 0;$skipCount 0;$emailBody h1当歌 Rss 订阅推送/h1ul;foreach ($items as $item) {// 获取链接及其他字段$link $isAtom? (string)($item-link[href]?? $item-link?? #) : (string)($item-link?? #);if (in_array($link, $existingLinks)) {$skipCount;continue;}$title (string)($item-title?? 无标题);$content $isAtom? (string)($item-content?? $item-summary?? ) : (string)($item-{content:encoded}?? $item-description?? );$pubDate $isAtom? (string)($item-published?? $item-updated?? date(Y-m-d H:i:s)) : (string)($item-pubDate?? date(Y-m-d H:i:s));try {$timestamp strtotime($pubDate);$formattedDate $timestamp? date(Y-m-d H:i:s, $timestamp) : date(Y-m-d H:i:s);// 插入新记录$stmt $pdo-prepare(INSERT INTO rss_items (user_id, rss_url, title, link, description, pub_date) VALUES (?,?,?,?,?,?));$stmt-execute([$userId,$url,$title,$link,$content,$formattedDate]);$newCount;$emailBody. listrong文章标题:/strong {$title}br.strong发布时间:/strong {$formattedDate}br.strong文章地址:/strong a href{$link}查看原文/a/li;} catch (PDOException $e) {error_log(插入 RSS 条目失败: . $e-getMessage());continue;}}$emailBody. /ul;// 检查是否首次执行及发送邮件//...}
}邮件推送 若有新内容且不是首次执行获取用户主邮箱和所有订阅邮箱合并去重后使用 PHPMailer 发送邮件通知邮件内容包含新文章的标题、发布时间和链接。
四邮件订阅功能
订阅流程 在 subscribe.php 中首先根据传入的密钥获取用户 ID 和用户名然后展示用户的订阅标题信息。 当用户提交邮箱时会检查是否在冷却时间内60 秒若不在则发送验证码到邮箱并记录相关信息到会话中。 当用户提交验证码时会验证验证码是否正确若正确则将订阅信息插入到 email_subscriptions 表中。 关键代码如下
$key $_GET[key]?? null;
if (!$key) {echo div classalert alert-danger无效的请求/div;exit;
}
// 验证密钥
$stmt $pdo-prepare(SELECT user_id FROM user_keys WHERE user_key ?);
$stmt-execute([$key]);
$userKey $stmt-fetch();
if (!$userKey) {echo div classalert alert-danger无效的密钥/div;exit;
}
$userId $userKey[user_id];// 获取用户名
$stmt $pdo-prepare(SELECT username FROM users WHERE id ?);
$stmt-execute([$userId]);
$user $stmt-fetch();
$keyUsername $user[username];// 获取订阅标题
$stmt $pdo-prepare(SELECT title, pub_date FROM rss_items WHERE user_id ? ORDER BY pub_date DESC LIMIT 5);
$stmt-execute([$userId]);
$subscriptions $stmt-fetchAll();if ($_SERVER[REQUEST_METHOD] POST isset($_POST[email])) {$currentTime time();if ($currentTime - $lastRequestTime $cooldown) {$message div classalert alert-warning请稍后 60 秒后再试。/div;} else {$email $_POST[email];$verificationCode rand(100000, 999999);// 发送验证码邮件$mail new PHPMailer(true);try {$mail-isSMTP();$mail-Host smtp.163.com;$mail-SMTPAuth true;$mail-Username xxxxx163.com;$mail-Password xxxxx;$mail-SMTPSecure PHPMailer::ENCRYPTION_STARTTLS;$mail-Port 25;$mail-CharSet UTF-8;$mail-setFrom(xxxxx163.com, RSS Notifier);$mail-addAddress($email);$mail-isHTML(true);$mail-Subject 当歌 Rss 订阅平台订阅验证码;$mail-Body 您的验证码是strong{$verificationCode}/strong;$mail-send();$message div classalert alert-success验证码已发送到您的邮箱请查收。/div;$showVerification true;$_SESSION[last_request_time] $currentTime;} catch (Exception $e) {$message div classalert alert-danger邮件发送失败: {$mail-ErrorInfo}/div;}$_SESSION[verification_code] $verificationCode;$_SESSION[email] $email;}
}if ($_SERVER[REQUEST_METHOD] POST isset($_POST[verification_code])) {$inputCode $_POST[verification_code];if ($inputCode $_SESSION[verification_code]) {// 验证成功订阅$stmt $pdo-prepare(INSERT INTO email_subscriptions (user_id, email, key_username, subscribed_at) VALUES (?,?,?, NOW()));$stmt-execute([$userId, $_SESSION[email], $keyUsername]);$message div classalert alert-success订阅成功/div;} else {$message div classalert alert-danger验证码错误请重试。/div;}
}平台地址
Dang.Ge