news 2026/9/20 11:53:22

PHP+MySQL新闻系统最小可行原型解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP+MySQL新闻系统最小可行原型解析

简介:本资源是一份面向高职院校软件技术专业学生的毕业设计(论文)完整文档,聚焦新闻发布系统的设计与实现,适用于课程设计、毕设参考及Web开发初学者实践学习。文档详细阐述了B/S架构下基于PHP+MySQL的动态新闻发布系统方案,涵盖前台新闻浏览/评论/用户注册/密码找回功能,以及后台管理员管理、记者投稿、编辑审核、新闻增删改、数据库备份恢复等核心模块,并附有可行性分析、进度计划、摘要与关键词等标准论文结构。资源为单文件Word文档(.doc格式),共1个文件,大小1.23MB,内容完整、排版规范,可直接用于答辩材料整理或功能逻辑参考。目前已有39人学习下载,适合需要快速掌握传统Web开发流程、理解权限分层设计与前后台协同机制的学习者。

1. 这不是“过时的毕业设计”,而是一份可复现的 B/S 架构新闻系统最小可行原型

2011 年的毕业设计文档,今天打开仍能直接跑通——这不是怀旧,而是因为它精准锚定了 Web 开发中一个长期稳定的技术交集:PHP + MySQL + HTML 静态化组合。它没用框架、不依赖 Composer、不卷前端工程化,却完整实现了用户登录、权限分级(管理员/记者/编辑/普通用户)、新闻 CRUD、评论互动、数据库备份恢复等真实业务闭环。对刚学完 PHP 基础语法、正卡在“写完代码怎么部署”阶段的新手,这份文档是少有的、带完整目录结构、SQL 脚本、页面跳转逻辑和权限判断细节的实战蓝本;对有 5 年经验的开发者,它暴露了早期 B/S 系统如何用mysql_*函数+手动 SQL 拼接+ cookie 权限标记来规避 XSS 和越权访问——这些原始写法,恰恰是理解现代 Laravel Gate 或 Spring Security 权限模型演进的起点。它解决的不是“高并发新闻推送”,而是“如何让三个人协作维护一个每天更新 10 条新闻的小站”,场景真实、边界清晰、无抽象概念堆砌。


2. PHP + MySQL + HTML 的三层协同机制:为什么这个组合在 2024 年仍值得拆解

2.1 技术选型背后的现实约束与工程权衡

这份设计没有选择当时已存在的 Zend Framework 或 CodeIgniter,原因很务实:开发环境是 Adobe Dreamweaver CS4,目标服务器是学生实训机房的 Windows XP + WAMP 组合,MySQL 版本锁定为 5.0。这意味着所有功能必须通过原生 PHP 函数实现,且不能依赖任何外部库。这种约束反而迫使设计者直面核心问题:

  • 数据层:用mysql_connect()建立连接后,所有查询都需手动拼接 SQL 字符串,password()函数加密密码(虽已废弃,但文档明确写出pass=password('$pass')),mysql_fetch_array($result, MYSQL_ASSOC)提取关联数组——这是 PHP 数据访问最原始的形态,也是理解 PDO::FETCH_ASSOC 本质的参照系;
  • 逻辑层:权限控制完全靠qx_flag字段数值判断(如if($A["flag"]!="3")),记者(flag=1)、编辑(flag=2)、管理员(flag=0)的路由分发全部硬编码在if-else中,没有中间件概念,但清晰展示了 RBAC 最简实现;
  • 表现层:前台页面用纯 HTML 生成静态结构,动态内容通过<?php echo $title; ?>插入,关键安全策略是“杜绝一般用户直接操作数据库”——即所有数据库交互必须经由 PHP 脚本中转,HTML 页面本身不包含任何数据库凭证或可执行逻辑。

提示:文档中conn.php是核心连接文件,其内容必然包含mysql_connect("localhost","root","")mysql_select_db("news")。2024 年复现时需替换为mysqli_connect(),但逻辑结构完全一致——这正是该设计的持久价值:它剥离了框架语法糖,只保留数据流主干。

2.2 数据库设计中的实体关系落地实践

系统共 4 张表,每张表的字段设计都服务于具体业务动作,而非理论范式:

2.2.1 用户表(user)的权限字段设计
字段名类型说明实际用途
idINT PK用户唯一标识作为外键关联评论表
nicknameVARCHAR(20)昵称登录账号,非邮箱
passVARCHAR(32)MD5 加密密码文档明确使用password()函数,对应 MySQL 内置哈希
qx_flagTINYINT权限标志0=管理员,1=记者,2=编辑,3=普通用户 —— 数值直接参与 PHP 条件判断
-- 创建 user 表的完整语句(根据文档表 4-3 补全) CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nickname` varchar(20) NOT NULL, `name` varchar(20) DEFAULT NULL, `pass` varchar(32) NOT NULL, `question` varchar(50) DEFAULT NULL, `answer` varchar(50) DEFAULT NULL, `qx_flag` tinyint(4) NOT NULL DEFAULT '3', `touxiang` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

注意:qx_flag的默认值3对应普通用户,意味着新注册用户无需审核即可浏览和评论,但无法进入后台——这种“默认开放读、限制写”的设计,是小型 CMS 的典型安全基线。

2.2.2 新闻表(news)的审核状态机

shenhe_flag字段是整个工作流的核心开关。记者发布新闻后,该字段初始为0(未审核);编辑审核通过后改为1;管理员可强制设为2(已删除)。前台页面的SELECT语句始终附加WHERE shenhe_flag=1,确保未审核内容不可见:

// 前台新闻列表查询(文档 5.1 节隐含逻辑) $sql = "SELECT * FROM news WHERE shenhe_flag=1 ORDER BY time DESC LIMIT 10"; $result = mysql_query($sql); while($row = mysql_fetch_array($result)) { echo "<h3>".$row['title']."</h3>"; echo "<p>".substr($row['data'],0,200)."...</p>"; // 截取前200字符预览 }

逻辑说明:shenhe_flag不是布尔值而是整数状态码,为后续扩展预留空间(如3=待编辑、4=已归档)。这种设计比简单is_approved字段更适应业务变化,且避免了频繁 ALTER TABLE。

2.2.3 评论表(pinglun)的关联与防灌水

pinglun表通过news_id外键关联news.id,但文档未声明外键约束——这是 MySQL MyISAM 引擎的常见做法(当时 InnoDB 未普及)。为防止刷评,系统在提交评论前检查$_SESSION$_COOKIE中的用户登录态,并记录publisher字段(用户昵称而非 ID),便于后台追溯:

// 评论提交处理(伪代码,基于文档 3.3 节描述) if (isset($_SESSION['user'])) { $news_id = intval($_POST['news_id']); // 强制转整型防 SQL 注入 $content = htmlspecialchars($_POST['content']); // 过滤 HTML 标签 $sql = "INSERT INTO pinglun (news_id, title, time, data, publisher) VALUES ($news_id, '$title', NOW(), '$content', '{$_SESSION['user']}')"; mysql_query($sql); }

参数说明:intval()htmlspecialchars()是当时最基础的防护手段,虽不如现代mysqli_real_escape_string()或 PDO 参数化查询严谨,但文档明确要求“杜绝一般用户直接操作数据库”,说明设计者已意识到输入验证必要性。

2.3 前后台分离的物理实现:目录结构即权限边界

文档 5.2 节提到“文件目录”,结合功能描述可还原出典型结构:

/news_system/ ├── index.php # 前台首页,显示审核通过的新闻 ├── login.php # 登录入口,验证后 setcookie ├── comment.php # 评论提交接口 ├── admin/ # 后台管理目录(需登录且 qx_flag=0) │ ├── index.php # 管理员总览 │ ├── add_news.php # 发布新闻(记者可用) │ └── audit.php # 审核列表(编辑专用) ├── conn.php # 数据库连接配置(含敏感信息,不应被直接访问) └── backup/ # 数据库备份脚本存放处(文档 4.3 节提及)

关键细节:admin/目录下每个 PHP 文件开头必有权限校验:

<?php session_start(); if (!isset($_SESSION['user']) || $_SESSION['flag'] != 0) { header("Location: ../login.php"); // 重定向到前台登录页 exit; } ?>

这种基于路径的物理隔离,是早期 Web 应用最朴素的访问控制,至今仍是 Nginx/Apache 的基础安全配置项。


3. 从文档到可运行环境:WAMP 下的逐行复现步骤与参数配置

3.1 环境搭建:用现代工具链还原 2011 年技术栈

虽然文档指定 Dreamweaver CS4 + MySQL 5.0,但 2024 年推荐使用XAMPP 8.2(含 PHP 8.2 + MySQL 8.0),因其兼容性好且一键安装。关键配置需手动调整以匹配文档:

3.1.1 MySQL 兼容性设置

MySQL 8.0 默认启用caching_sha2_password认证插件,而文档中的mysql_*函数仅支持mysql_native_password。需修改 root 用户认证方式:

-- 在 MySQL 命令行执行 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY ''; FLUSH PRIVILEGES;

逻辑说明:mysql_*函数已被 PHP 7.0+ 移除,但 XAMPP 8.2 仍提供mysqli扩展。复现时需将所有mysql_connect()替换为mysqli_connect(),并将mysql_query($sql)改为mysqli_query($conn, $sql),其中$connmysqli_connect()返回的连接资源。

3.1.2 PHP 配置关键参数

编辑xampp/php/php.ini,确保以下参数启用:

参数推荐值作用
extension=mysqli取消注释启用 MySQLi 扩展
session.save_path"C:/xampp/tmp"设置 Session 存储路径(Windows 下需存在该目录)
display_errorsOn开发阶段显示错误,便于调试
error_reportingE_ALL & ~E_NOTICE屏蔽 Notice 级别警告(因文档代码存在未定义变量)

注意:文档中大量使用$_POST["enter"]=="登录"这类写法,PHP 8.0+ 会触发Undefined array key警告,故需降低错误报告级别。

3.2 数据库初始化:执行文档中的 CREATE DATABASE 脚本

文档 4.5 节的CREATE DATABASE news语句存在路径硬编码(D:\project\),需修改为 XAMPP 默认路径:

-- 创建数据库(适配 XAMPP) CREATE DATABASE IF NOT EXISTS `news` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 选择数据库 USE `news`; -- 创建 user 表(补全文档缺失的 ENGINE 和 CHARSET) CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nickname` varchar(20) NOT NULL, `name` varchar(20) DEFAULT NULL, `pass` varchar(32) NOT NULL, `question` varchar(50) DEFAULT NULL, `answer` varchar(50) DEFAULT NULL, `qx_flag` tinyint(4) NOT NULL DEFAULT '3', `touxiang` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 插入默认管理员(文档 4.3 节提及) INSERT INTO `user` (`nickname`, `pass`, `qx_flag`) VALUES ('admin', '21232f297a57a5a743894a0e4a801fc3', '0'); -- MD5('admin')

参数说明:21232f297a57a5a743894a0e4a801fc3md5("admin")的结果,文档虽用password()函数,但实际效果等同于 MD5。utf8mb4支持 emoji,比文档的utf8更健壮。

3.3 核心功能验证:三步走通新闻发布全流程

3.3.1 前台浏览:验证静态 HTML 与动态 PHP 的混合渲染

访问http://localhost/news_system/index.php,应看到新闻标题列表。若报错Fatal error: Uncaught Error: Call to undefined function mysql_connect(),说明未替换函数。正确修复后,页面应显示:

<!-- index.php 片段 --> <?php include "conn.php"; ?> <?php $sql = "SELECT * FROM news WHERE shenhe_flag=1 ORDER BY time DESC LIMIT 5"; $result = mysqli_query($conn, $sql); while($row = mysqli_fetch_assoc($result)) { echo "<div class='news-item'>"; echo "<h2>".$row['title']."</h2>"; echo "<p>".date('Y-m-d', strtotime($row['time']))." | 浏览 ".$row['number']." 次</p>"; echo "<p>".mb_substr($row['data'],0,150,'UTF-8')."...</p>"; echo "<a href='detail.php?id=".$row['id']."'>查看详情</a>"; echo "</div>"; } ?>

逻辑说明:mb_substr()替代substr()解决中文截断乱码,strtotime()将 MySQL 时间戳转为 PHP 可读格式——这些是文档未写但实际必需的细节。

3.3.2 后台登录:Cookie 权限传递的实操验证

登录页面login.php提交后,检查浏览器 Cookie 是否存在userflag

// login.php 验证逻辑(修正版) if ($_POST['enter'] === '登录') { $nicheng = mysqli_real_escape_string($conn, $_POST['nicheng']); $pass = md5($_POST['pass']); // 替换 password() 函数 $sql = "SELECT * FROM user WHERE nickname='$nicheng' AND pass='$pass'"; $result = mysqli_query($conn, $sql); if ($row = mysqli_fetch_assoc($result)) { setcookie("user", $nicheng, time()+3600, "/"); setcookie("flag", $row['qx_flag'], time()+3600, "/"); header("Location: admin/index.php"); exit; } else { echo "用户名或密码错误"; } }

参数说明:setcookie()第四个参数/表示 Cookie 对整个域名有效,避免子目录访问失效;time()+3600设定 1 小时有效期,比文档的永久 Cookie 更安全。

3.3.3 新闻审核:状态机驱动的后台操作

访问http://localhost/news_system/admin/audit.php,应列出shenhe_flag=0的新闻。点击“通过”按钮时,执行:

// audit.php 中的审核操作 if (isset($_GET['action']) && $_GET['action']=='pass' && isset($_GET['id'])) { $id = intval($_GET['id']); $sql = "UPDATE news SET shenhe_flag=1 WHERE id=$id"; mysqli_query($conn, $sql); header("Location: audit.php"); }

验证方法:在 MySQL 命令行执行SELECT * FROM news WHERE shenhe_flag=0;,确认有未审核记录;操作后再次查询,shenhe_flag应变为1,且前台index.php刷新后出现新新闻。


4. 安全加固与现代适配:把毕业设计变成生产级最小系统

4.1 输入验证升级:从 htmlspecialchars 到参数化查询

文档中$_POST["nicheng"]直接拼入 SQL 是重大风险。2024 年必须升级为预处理语句:

// 安全的登录验证(替代原文档 5.1 节代码) $stmt = $conn->prepare("SELECT * FROM user WHERE nickname = ? AND pass = ?"); $stmt->bind_param("ss", $nicheng, $pass_hash); $stmt->execute(); $result = $stmt->get_result(); if ($row = $result->fetch_assoc()) { // 登录成功 }

逻辑说明:bind_param("ss", $nicheng, $pass_hash)"ss"表示两个字符串参数,MySQLi 自动转义,彻底杜绝 SQL 注入。$pass_hash需提前用md5()或更安全的password_hash()生成。

4.2 权限模型重构:用 Session 替代 Cookie 存储敏感标识

文档用setcookie("flag", $row['qx_flag'])存储权限,易被篡改。应改为 Session:

// login.php 中 session_start(); $_SESSION['user'] = $row['nickname']; $_SESSION['flag'] = $row['qx_flag']; // 仅存于服务器内存 $_SESSION['id'] = $row['id']; // 后台校验 session_start(); if (!isset($_SESSION['user']) || $_SESSION['flag'] != 0) { header("Location: ../login.php"); exit; }

优势:Session 数据存储在服务器端,客户端只保存PHPSESSIDCookie,无法直接修改权限值。

4.3 静态资源优化:HTML5 语义化与响应式基础

文档使用传统<table>布局,现代复现应添加 HTML5 结构:

<!-- index.php 的新闻列表部分 --> <main> <article class="news-item"> <header> <h2><?php echo htmlspecialchars($row['title']); ?></h2> <time datetime="<?php echo date('c', strtotime($row['time'])); ?>"> <?php echo date('Y年m月d日', strtotime($row['time'])); ?> </time> </header> <section> <p><?php echo htmlspecialchars(mb_substr($row['data'],0,150,'UTF-8')); ?>...</p> <a href="detail.php?id=<?php echo $row['id']; ?>">阅读全文</a> </section> </article> </main>

参数说明:<time>标签提供机器可读时间,datetime属性值date('c')输出 ISO 8601 格式(如2024-06-15T14:30:00+08:00),利于 SEO 和无障碍访问;htmlspecialchars()防止 XSS,比文档的纯echo更安全。

4.4 数据库备份自动化:用 mysqldump 替代手工导出

文档 4.3 节提及“文件的初始化、备份”,但未给脚本。可添加backup.php

<?php // backup.php - 需管理员权限调用 if ($_SESSION['flag'] != 0) die('Access denied'); $backup_file = 'backup_'.date('Ymd_His').'.sql'; $command = "mysqldump -u root --no-password news > C:/xampp/htdocs/news_system/backup/$backup_file"; exec($command, $output, $return_code); if ($return_code === 0) { echo "备份成功:$backup_file"; } else { echo "备份失败"; } ?>

验证技巧:在 XAMPP 控制面板启动 Shell,执行mysqldump -u root news > test.sql测试命令是否可用;--no-password要求 root 用户密码为空(即 3.1.1 节设置),否则需添加-p参数并交互输入。


5. 功能延伸与边界突破:用原生 PHP 实现文档未写的实用特性

5.1 新闻图片上传:PHP 文件处理的最小实现

文档未提图片,但新闻必然需要配图。在add_news.php中添加:

// 图片上传处理 if ($_FILES['image']['error'] == UPLOAD_ERR_OK) { $upload_dir = 'uploads/'; $file_name = uniqid().'_'.$_FILES['image']['name']; $target_path = $upload_dir . $file_name; // 验证文件类型 $allowed_types = ['image/jpeg', 'image/png', 'image/gif']; if (in_array($_FILES['image']['type'], $allowed_types)) { if (move_uploaded_file($_FILES['image']['tmp_name'], $target_path)) { $image_path = $target_path; } } } // 插入新闻时保存图片路径 $sql = "INSERT INTO news (type, title, time, publisher, data, image_path) VALUES (?, ?, NOW(), ?, ?, ?)"; $stmt = $conn->prepare($sql); $stmt->bind_param("issis", $type, $title, $publisher, $content, $image_path); $stmt->execute();

关键参数:uniqid()生成唯一文件名防覆盖;move_uploaded_file()是 PHP 文件上传的标准函数;$image_path存入数据库,前台用<img src="<?php echo $row['image_path']; ?>">显示。

5.2 分页功能:LIMIT OFFSET 的实战应用

文档新闻列表无分页,大数据量时会崩溃。在index.php添加:

// 分页计算 $per_page = 10; $page = isset($_GET['page']) ? intval($_GET['page']) : 1; $offset = ($page - 1) * $per_page; // 查询总数用于分页链接 $total_sql = "SELECT COUNT(*) as total FROM news WHERE shenhe_flag=1"; $total_result = mysqli_query($conn, $total_sql); $total_row = mysqli_fetch_assoc($total_result); $total = $total_row['total']; $pages = ceil($total / $per_page); // 查询当前页数据 $sql = "SELECT * FROM news WHERE shenhe_flag=1 ORDER BY time DESC LIMIT $per_page OFFSET $offset"; $result = mysqli_query($conn, $sql); // 生成分页链接 for ($i = 1; $i <= $pages; $i++) { echo "<a href='?page=$i'>$i</a> "; }

逻辑说明:OFFSET值随页码线性增长,当$page很大时(如第 1000 页),OFFSET 9990会导致 MySQL 全表扫描,此时应改用WHERE id < last_id的游标分页——这是文档未触及但生产环境必遇的性能瓶颈。

5.3 密码找回:基于安全问题的二次验证

文档 3.3 节提到“忘记密码时可以通过提示问题找回密码”,实现如下:

// findpass.php if ($_POST['action'] == 'verify') { $nicheng = mysqli_real_escape_string($conn, $_POST['nicheng']); $sql = "SELECT question, answer FROM user WHERE nickname='$nicheng'"; $result = mysqli_query($conn, $sql); if ($row = mysqli_fetch_assoc($result)) { $_SESSION['reset_user'] = $nicheng; $_SESSION['security_question'] = $row['question']; // 显示问题,等待用户输入答案 } } if ($_POST['action'] == 'reset' && isset($_SESSION['reset_user'])) { $answer = mysqli_real_escape_string($conn, $_POST['answer']); $sql = "SELECT answer FROM user WHERE nickname='{$_SESSION['reset_user']}'"; $result = mysqli_query($conn, $sql); if ($row = mysqli_fetch_assoc($result) && $row['answer'] == $answer) { // 生成新密码并更新 $new_pass = substr(md5(time().rand()),0,8); $update_sql = "UPDATE user SET pass='".md5($new_pass)."' WHERE nickname='{$_SESSION['reset_user']}'"; mysqli_query($conn, $update_sql); echo "新密码:$new_pass"; } }

安全提示:生产环境应禁用明文返回密码,改为发送重置链接到注册邮箱;此处为复现文档逻辑,采用最简方案。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 11:50:26

DCT-Net 人像卡通化,让 Codex 走 TaoToken 补全 pipeline 行不行

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 11:50:14

6脚三位一体数码管实战:从引脚识别到C语言动态扫描驱动

搞单片机这些年&#xff0c;数码管绝对是我用过最皮实的显示器件——便宜、耐操、显示效果又直观。但很多刚入门的兄弟第一次拿到那种“三位一体、只有6只脚”的数码管时&#xff0c;当场就懵了&#xff1a;三个数字不就得12根线吗&#xff1f;6根线怎么玩&#xff1f;其实这类…

作者头像 李华
网站建设 2026/9/20 11:50:04

基于微信小程序与STM32的智能药盒管理系统

简介&#xff1a;一套结合微信小程序与STM32的智能药盒管理系统完整方案&#xff0c;以小程序作为交互入口、STM32作为控制核心&#xff0c;构成端云联动的物联网用药管理方案。主要面向嵌入式开发者、物联网爱好者及医疗健康产品设计人员&#xff0c;解决传统用药管理依赖人工…

作者头像 李华
网站建设 2026/9/20 11:48:45

OpenMMO程序化路网:连接定居点的道路网络生成算法指南

OpenMMO程序化路网&#xff1a;连接定居点的道路网络生成算法指南 【免费下载链接】OpenMMO 项目地址: https://gitcode.com/GitHub_Trending/open/OpenMMO OpenMMO 是一款程序化生成的开放世界 MMO&#xff0c;它的路网系统&#xff08;Road Network&#xff09;完全由…

作者头像 李华