本文目录导读:

我来详细介绍如何用 PHP 实现一个公告系统。
数据库设计
首先创建公告表:
CREATE TABLE announcements (
id INT PRIMARY KEY AUTO_INCREMENT,VARCHAR(200) NOT NULL COMMENT '公告标题',
content TEXT NOT NULL COMMENT '公告内容',
type TINYINT DEFAULT 1 COMMENT '公告类型:1-通知 2-活动 3-紧急',
status TINYINT DEFAULT 1 COMMENT '状态:1-发布 0-草稿 2-下架',
priority INT DEFAULT 0 COMMENT '优先级,越大越靠前',
start_time DATETIME COMMENT '开始展示时间',
end_time DATETIME COMMENT '结束展示时间',
created_by INT COMMENT '创建人ID',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_status_time (status, start_time, end_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
公告核心类
<?php
class Announcement {
private $db;
public function __construct($db) {
$this->db = $db;
}
// 发布公告
public function create($data) {
$sql = "INSERT INTO announcements (title, content, type, status, priority, start_time, end_time, created_by)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $this->db->prepare($sql);
return $stmt->execute([
$data['title'],
$data['content'],
$data['type'] ?? 1,
$data['status'] ?? 1,
$data['priority'] ?? 0,
$data['start_time'] ?? date('Y-m-d H:i:s'),
$data['end_time'] ?? null,
$data['created_by'] ?? 0
]);
}
// 获取有效公告列表
public function getActiveList($page = 1, $limit = 10) {
$offset = ($page - 1) * $limit;
$now = date('Y-m-d H:i:s');
$sql = "SELECT * FROM announcements
WHERE status = 1
AND (start_time IS NULL OR start_time <= ?)
AND (end_time IS NULL OR end_time >= ?)
ORDER BY priority DESC, created_at DESC
LIMIT ? OFFSET ?";
$stmt = $this->db->prepare($sql);
$stmt->execute([$now, $now, $limit, $offset]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 获取公告详情
public function getById($id) {
$sql = "SELECT * FROM announcements WHERE id = ? AND status = 1";
$stmt = $this->db->prepare($sql);
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
// 更新公告
public function update($id, $data) {
$sql = "UPDATE announcements SET
title = ?, content = ?, type = ?, status = ?, priority = ?,
start_time = ?, end_time = ? WHERE id = ?";
$stmt = $this->db->prepare($sql);
return $stmt->execute([
$data['title'],
$data['content'],
$data['type'],
$data['status'],
$data['priority'],
$data['start_time'],
$data['end_time'],
$id
]);
}
// 删除公告(软删除)
public function delete($id) {
$sql = "UPDATE announcements SET status = 2 WHERE id = ?";
$stmt = $this->db->prepare($sql);
return $stmt->execute([$id]);
}
}
前端页面示例
公告列表页面
<?php
// 引入数据库连接
require_once 'db.php';
require_once 'Announcement.php';
$announcement = new Announcement($db);
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$list = $announcement->getActiveList($page, 10);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">公告系统</title>
<style>
.announcement-list { max-width: 800px; margin: 0 auto; }
.announcement-item {
border: 1px solid #ddd;
margin: 10px 0;
padding: 15px;
border-radius: 5px;
}
.announcement-title { font-weight: bold; font-size: 1.2em; color: #333; }
.announcement-meta { color: #999; font-size: 0.8em; margin-top: 10px; }
.announcement-type {
display: inline-block;
padding: 2px 8px;
border-radius: 3px;
font-size: 0.8em;
background: #e3f2fd;
color: #1976d2;
}
.type-urgent { background: #ffebee; color: #c62828; }
.type-activity { background: #f3e5f5; color: #8e24aa; }
</style>
</head>
<body>
<div class="announcement-list">
<h1>最新公告</h1>
<?php foreach ($list as $item): ?>
<div class="announcement-item">
<div class="announcement-title">
<?php echo htmlspecialchars($item['title']); ?>
</div>
<div class="announcement-type type-<?php echo $item['type']; ?>">
<?php echo getTypeName($item['type']); ?>
</div>
<div class="announcement-content">
<?php echo mb_substr(strip_tags($item['content']), 0, 100) . '...'; ?>
</div>
<div class="announcement-meta">
发布于: <?php echo date('Y-m-d', strtotime($item['created_at'])); ?>
</div>
</div>
<?php endforeach; ?>
</div>
</body>
</html>
<?php
function getTypeName($type) {
$types = [1 => '通知', 2 => '活动', 3 => '紧急'];
return $types[$type] ?? '通知';
}
?>
公告管理后台
<?php
// 后台管理页面(仅为简化示例)
require_once 'db.php';
require_once 'Announcement.php';
$announcement = new Announcement($db);
// 处理表单提交
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['action'])) {
switch ($_POST['action']) {
case 'create':
$announcement->create($_POST);
break;
case 'update':
$announcement->update($_POST['id'], $_POST);
break;
case 'delete':
$announcement->delete($_POST['id']);
break;
}
}
}
?>
核心功能实现
公告缓存优化(Redis)
<?php
class AnnouncementCache {
private $redis;
public function __construct($redis) {
$this->redis = $redis;
}
// 获取公告列表(带缓存)
public function getListWithCache($page = 1, $limit = 10) {
$cacheKey = "announcement:list:{$page}:{$limit}";
// 尝试从缓存获取
$cached = $this->redis->get($cacheKey);
if ($cached) {
return json_decode($cached, true);
}
// 从数据库获取
$list = $this->getFromDB($page, $limit);
// 写入缓存,设置过期时间10分钟
$this->redis->setex($cacheKey, 600, json_encode($list));
return $list;
}
// 清除缓存
public function clearCache() {
$keys = $this->redis->keys('announcement:list:*');
if ($keys) {
$this->redis->del($keys);
}
}
}
?>
高级功能实现
公告推送功能(WebSocket)
<?php
// 使用简单的长轮询或定期检查
class AnnouncementPusher {
private $db;
// 检查新公告
public function checkNewAnnouncements($lastCheckTime) {
$sql = "SELECT * FROM announcements
WHERE created_at > ? AND status = 1
ORDER BY created_at DESC";
$stmt = $this->db->prepare($sql);
$stmt->execute([$lastCheckTime]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 推送公告到前端
public function pushToClient() {
$newAnnouncements = $this->checkNewAnnouncements($this->getLastCheckTime());
if (!empty($newAnnouncements)) {
echo json_encode([
'status' => 'new',
'data' => $newAnnouncements
]);
} else {
echo json_encode(['status' => 'no_new']);
}
}
}
?>
阅读记录功能
CREATE TABLE announcement_reads (
id INT PRIMARY KEY AUTO_INCREMENT,
announcement_id INT NOT NULL,
user_id INT NOT NULL,
read_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_user_announcement (user_id, announcement_id)
);
<?php
class AnnouncementRead {
private $db;
// 标记为已读
public function markAsRead($announcementId, $userId) {
$sql = "INSERT INTO announcement_reads (announcement_id, user_id)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE read_at = CURRENT_TIMESTAMP";
$stmt = $this->db->prepare($sql);
return $stmt->execute([$announcementId, $userId]);
}
// 获取用户未读公告数
public function getUnreadCount($userId) {
$sql = "SELECT COUNT(*) FROM announcements a
WHERE a.status = 1
AND a.id NOT IN (
SELECT announcement_id FROM announcement_reads WHERE user_id = ?
)";
$stmt = $this->db->prepare($sql);
$stmt->execute([$userId]);
return $stmt->fetchColumn();
}
}
?>
安全建议
- XSS防护:输出时使用
htmlspecialchars() - SQL注入防护:使用PDO预处理语句
- 权限控制:区分管理员和普通用户
- CSRF防护:添加Token验证
- 数据验证:输入数据严格验证
性能优化建议
- 使用Redis缓存公告数据
- 对大列表进行分页处理
- 建立合适的数据库索引字段使用TEXT类型,避免过大
- 定期清理过期的公告
这个公告系统实现了基本的功能,你可以根据实际需求进行扩展,比如添加附件上传、公告分类、全文搜索等功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播