PHP 怎么实现公告系统

wen PHP项目 1

本文目录导读:

PHP 怎么实现公告系统

  1. 数据库设计
  2. 公告核心类
  3. 前端页面示例
  4. 核心功能实现
  5. 高级功能实现
  6. 安全建议
  7. 性能优化建议

我来详细介绍如何用 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();
    }
}
?>

安全建议

  1. XSS防护:输出时使用htmlspecialchars()
  2. SQL注入防护:使用PDO预处理语句
  3. 权限控制:区分管理员和普通用户
  4. CSRF防护:添加Token验证
  5. 数据验证:输入数据严格验证

性能优化建议

  • 使用Redis缓存公告数据
  • 对大列表进行分页处理
  • 建立合适的数据库索引字段使用TEXT类型,避免过大
  • 定期清理过期的公告

这个公告系统实现了基本的功能,你可以根据实际需求进行扩展,比如添加附件上传、公告分类、全文搜索等功能。

抱歉,评论功能暂时关闭!