教程大纲
- 核心概念理解:在写任何代码之前,我们必须明白 PHP 和 MySQL 是如何协同工作的。
- 环境搭建:在你的电脑上创建一个可以运行 PHP 和 MySQL 的本地环境。
- 数据库设计:学习如何为你的网站设计数据结构。
- PHP 与 MySQL 连接:编写 PHP 代码连接到你的数据库。
- 实现核心功能:学习增、删、改、查 这四个数据库操作的核心。
- 实战案例:一个简单的文章管理系统:将所有知识点串联起来,动手做一个完整的小项目。
- 安全与最佳实践:介绍如何防止 SQL 注入等常见安全问题。
- 进阶学习与资源:告诉你学完基础后,下一步该去哪里。
核心概念理解:MVC 思想入门
在传统且简单的 PHP 网站布局中,我们通常遵循一种类似 MVC(Model-View-Controller) 的简化思想,它将网站分为三个主要部分:

(图片来源网络,侵删)
-
Model (模型) - 数据层
- 作用:负责所有与数据库相关的操作,连接数据库、执行 SQL 查询、获取数据、保存数据等。
- 比喻:图书馆的图书管理员,他只负责管理图书(数据),不关心图书如何展示给读者。
-
View (视图) - 表现层
- 作用:负责展示数据,它通常是包含 HTML 和少量 PHP 代码的文件,这些 PHP 代码的主要任务是显示从模型层获取的数据。
- 比喻:图书的封面和内页,它只负责展示图书内容(数据),本身不包含任何逻辑。
-
Controller (控制器) - 逻辑层
- 作用:网站的“大脑”,它接收用户的请求(比如点击一个链接),调用模型层获取或处理数据,然后将数据传递给视图层进行展示。
- 比喻:图书借阅处的服务员,读者(用户)告诉他想借什么书(请求),他去书库(模型)找书,然后把书交给读者(视图展示)。
流程总结:

(图片来源网络,侵删)
- 用户请求 -> 控制器 接收请求。
- 控制器 调用 模型 去数据库获取数据。
- 模型 执行 SQL,将数据返回给 控制器。
- 控制器 将数据传递给 视图。
- 视图 渲染最终的 HTML 页面,并展示给 用户。
文件结构示例:
my_website/
├── config.php # 数据库连接配置 (可以看作是模型的一部分)
├── index.php # 首页控制器和视图 (简单项目里可能混在一起)
├── about.php # 关于页面控制器和视图
├── articles/
│ ├── list.php # 文章列表控制器和视图
│ └── view.php # 查看单篇文章控制器和视图
├── models/
│ └── article_model.php # 专门处理文章数据的模型 (进阶用法)
└── includes/
└── header.php # 页头视图 (可复用)
└── footer.php # 页脚视图 (可复用)
环境搭建
你需要在本地电脑上安装一个服务器环境,才能运行 PHP 和 MySQL,最简单的方法是使用集成环境包。
推荐工具:
- XAMPP (跨平台: Windows, macOS, Linux): 最流行,功能齐全。
- WampServer (仅 Windows): Windows 用户首选,安装简单。
- MAMP (仅 macOS): macOS 用户首选。
安装步骤(以 XAMPP 为例):
- 下载:从 XAMPP 官网 下载适合你操作系统的版本。
- 安装:像安装普通软件一样进行安装。
- 启动:安装完成后,打开 XAMPP Control Panel。
- 启动服务:点击 Apache 和 MySQL 模块的 Start 按钮,这两个服务是必须的。
- 验证:
- 在浏览器地址栏输入
http://localhost或http://127.0.0.1,如果看到 XAMPP 的欢迎页面,说明 Apache 服务器已成功运行。 - 在浏览器地址栏输入
http://localhost/phpmyadmin,如果看到一个管理数据库的界面,说明 MySQL 已成功运行。
- 在浏览器地址栏输入
你的网站根目录:默认情况下,你所有的网站文件都应该放在 XAMPP 的 htdocs 文件夹里,在 Windows 上,路径通常是 C:\xampp\htdocs。
数据库设计
假设我们要做一个简单的文章管理系统,需要存储文章信息。
步骤:
- 打开
http://localhost/phpmyadmin。 - 在首页的 "创建数据库" 输入框中,输入数据库名,
my_blog,然后点击创建。 - 在左侧选择
my_blog数据库。 - 点击顶部的 "SQL" 选项卡,在文本框中输入以下 SQL 语句来创建一个
articles表:
CREATE TABLE articles (
id INT(11) AUTO_INCREMENT PRIMARY KEY,VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
SQL 语句解释:
CREATE TABLE articles (...): 创建一个名为articles的新表。id INT(11) AUTO_INCREMENT PRIMARY KEY: 创建一个id字段,它是整数类型,会自动递增(每插入一条新记录,id 自动+1),并且是主键(每条记录的唯一标识),VARCHAR(255) NOT NULL创建一个title` 字段,它是一个最大长度为255的字符串,并且不能为空。content TEXT NOT NULL: 创建一个content字段,用于存放长文本,也不能为空。created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP: 创建一个created_at字段,用于记录文章创建时间,默认值为当前时间。
PHP 与 MySQL 连接
我们需要一个 PHP 文件来管理数据库连接信息,这样其他文件只需要包含这个文件即可,方便维护。
创建 config.php 文件,并放在 htdocs 目录下:
<?php
// 数据库配置信息
define('DB_HOST', 'localhost');
define('DB_USER', 'root'); // XAMPP默认用户名
define('DB_PASS', ''); // XAMPP默认密码为空
define('DB_NAME', 'my_blog');
// 创建连接
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
// 检查连接是否成功
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
// 设置字符集,防止中文乱码
$conn->set_charset("utf8mb4");
?>
解释:
mysqli: 这是 PHP 中用于操作 MySQL 数据库的一个扩展。new mysqli(...): 创建一个新的数据库连接对象。connect_error: 如果连接失败,这个属性会包含错误信息。die(...): 如果连接失败,输出错误信息并终止脚本执行。set_charset("utf8mb4"): 非常重要! 设置数据库连接的字符集为utf8mb4,它可以完美支持包括 Emoji 在内的所有 Unicode 字符,避免乱码问题。
实现核心功能
现在我们有了数据库和连接,就可以开始进行增、删、改、查操作了,我们将在一个文件中实现这些功能。
创建 index.php 文件:
<?php
// 1. 引入数据库连接文件
require_once 'config.php';
// --- C: Create (新增文章) ---
// 检查是否是通过 POST 请求提交的表单
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['title']) && isset($_POST['content'])) {
$title = $_POST['title'];
$content = $_POST['content'];
// 使用预处理语句来防止 SQL 注入
$stmt = $conn->prepare("INSERT INTO articles (title, content) VALUES (?, ?)");
$stmt->bind_param("ss", $title, $content); // "ss" 表示两个字符串参数
if ($stmt->execute()) {
echo "文章创建成功!";
} else {
echo "Error: " . $stmt->error;
}
$stmt->close();
}
// --- R: Read (读取文章列表) ---
$sql = "SELECT id, title, created_at FROM articles ORDER BY created_at DESC";
$result = $conn->query($sql);
// --- U: Update (更新文章) ---
// V: Delete (删除文章)
// ... (我们将在实战案例中实现这些)
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">我的博客</title>
<style>
body { font-family: sans-serif; margin: 20px; }
.article { border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; }
.article h2 { margin: 0 0 10px 0; }
.article a { text-decoration: none; color: #0056b3; }
.form-container { background: #f4f4f4; padding: 15px; margin-bottom: 20px; border-radius: 5px; }
</style>
</head>
<body>
<h1>欢迎来到我的博客</h1>
<!-- 新增文章的表单 (View部分) -->
<div class="form-container">
<h2>发表新文章</h2>
<form action="index.php" method="POST">
<label for="title">标题:</label><br>
<input type="text" id="title" name="title" size="50" required><br><br>
<label for="content">内容:</label><br>
<textarea id="content" name="content" rows="5" cols="50" required></textarea><br><br>
<input type="submit" value="发布">
</form>
</div>
<!-- 显示文章列表 (View部分) -->
<h2>文章列表</h2>
<?php
if ($result->num_rows > 0) {
// 输出每条数据
while($row = $result->fetch_assoc()) {
echo '<div class="article">';
echo '<h2><a href="view.php?id=' . $row["id"] . '">' . htmlspecialchars($row["title"]) . '</a></h2>';
echo '<p>发布于: ' . $row["created_at"] . '</p>';
echo '</div>';
}
} else {
echo "暂无文章";
}
?>
<?php
// 5. 关闭连接
$conn->close();
?>
</body>
</html>
代码解析:
require_once 'config.php';: 包含我们的数据库连接文件。- Create (新增):
if ($_SERVER["REQUEST_METHOD"] == "POST" ...): 判断页面是否是通过表单提交的。$_POST: 一个超全局数组,用于获取通过 POST 方法提交的数据。- 预处理语句 (
prepare,bind_param,execute): 这是防止 SQL 注入攻击的标准做法,它将 SQL 语句和数据分离开,数据库会先编译 SQL 语句,再将数据作为参数传入,从而杜绝了恶意代码被执行的可能。 bind_param("ss", $title, $content): "ss" 表示接下来的两个参数都是字符串。
- Read (读取):
$sql = "SELECT ...": 编写 SQL 查询语句,获取所有文章的 id, title 和 created_at,并按发布时间倒序排列。$conn->query($sql): 执行查询。$result->num_rows > 0: 检查查询结果是否有数据。while($row = $result->fetch_assoc()): 循环遍历结果集。fetch_assoc()会将当前行数据作为一个关联数组返回($row['title'])。htmlspecialchars($row["title"]): 一个非常重要的安全函数,用于将特殊字符(如<,>,&)转换为 HTML 实体,防止 XSS (跨站脚本) 攻击。
- 关闭连接:
$conn->close();在脚本最后关闭数据库连接,释放资源。
实战案例:一个简单的文章管理系统
我们基于 index.php,创建 view.php 来查看单篇文章,并增加编辑和删除功能。
创建 view.php 文件:
<?php
require_once 'config.php';
// 检查 URL 中是否有 id 参数
if (!isset($_GET['id']) || empty($_GET['id'])) {
die("文章 ID 未指定!");
}
$id = $_GET['id'];
// --- R: Read (读取单篇文章) ---
// 使用预处理语句防止 SQL 注入
$stmt = $conn->prepare("SELECT id, title, content, created_at FROM articles WHERE id = ?");
$stmt->bind_param("i", $id); // "i" 表示一个整数参数
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$article = $result->fetch_assoc();
} else {
die("文章不存在!");
}
$stmt->close();
$conn->close();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"><?php echo htmlspecialchars($article['title']); ?></title>
<style>
body { font-family: sans-serif; margin: 20px; line-height: 1.6; }
.article h1 { color: #333; }
.article-meta { color: #777; font-size: 0.9em; margin-bottom: 20px; }
.back-link { display: block; margin-bottom: 20px; }
</style>
</head>
<body>
<a href="index.php" class="back-link">← 返回文章列表</a>
<div class="article">
<h1><?php echo htmlspecialchars($article['title']); ?></h1>
<p class="article-meta">发布于: <?php echo $article['created_at']; ?></p>
<hr>
<p><?php echo nl2br(htmlspecialchars($article['content'])); ?></p>
</div>
</body>
</html>
代码解析:
- 我们通过
$_GET['id']从 URL 中获取要查看的文章 ID。 - 使用
prepare和bind_param再次安全地查询数据库。 get_result(): 获取预处理语句的查询结果集。nl2br(): 一个有用的函数,将字符串中的换行符\n转换成 HTML 的<br>标签,这样文章内容就能正确换行了。
安全与最佳实践
我们已经在上面的代码中使用了两个最重要的安全实践:
-
防止 SQL 注入:
- 方法:始终使用 预处理语句 和 参数绑定 (
prepare,bind_param,execute)。 - 为什么:它将 SQL 逻辑和数据完全分离,确保用户输入的数据不会被当作 SQL 代码来执行。
- 方法:始终使用 预处理语句 和 参数绑定 (
-
防止 XSS (跨站脚本) 攻击:
- 方法:在输出任何用户提交的数据到 HTML 页面之前,使用
htmlspecialchars()函数。 - 为什么:这个函数会把
<,>,&, , 等字符转换成 HTML 实体,这样,即使用户提交了<script>alert('hacked')</script>这样的恶意代码,浏览器也会将其作为纯文本显示,而不是执行它。
- 方法:在输出任何用户提交的数据到 HTML 页面之前,使用
其他最佳实践:
- 错误处理:在生产环境中,不要直接向用户显示数据库错误信息(如
die($conn->connect_error)),这会暴露服务器的敏感信息,应该记录日志,并向用户显示一个友好的错误页面。 - 文件分离:随着项目变大,将控制器、模型、视图分离到不同的文件夹中,使代码结构更清晰。
- 使用 PDO:
PDO (PHP Data Objects)是另一种数据库访问抽象层,它比mysqli更灵活,因为它可以轻松切换不同类型的数据库(如 MySQL, PostgreSQL, SQLite),虽然mysqli也很强大,但 PDO 是更现代和推荐的选择。
进阶学习与资源
当你掌握了以上基础后,可以开始学习更高级的主题:
- 面向对象编程:将你的模型和控制器封装成类,使代码更易于管理和复用。
- MVC 框架:学习使用成熟的 PHP 框架,如 Laravel 或 Symfony,它们为你提供了强大的工具(路由、ORM、模板引擎等),让你能更专注于业务逻辑,而不是重复造轮子。
- RESTful API:学习如何构建 API,为你的移动 App 或前端 JavaScript 框架(如 Vue, React)提供数据。
- 前端技术:学习 HTML5, CSS3, JavaScript,以及 jQuery 或现代前端框架,让你的网站交互更丰富。
推荐资源:
- 官方文档:PHP.net, MySQL.com
- 免费教程网站:W3Schools, MDN Web Docs
- 视频教程:YouTube, Bilibili 上有大量免费且高质量的 PHP/MySQL 教程。
- 社区:Stack Overflow 是解决编程问题的绝佳去处。
这份教程为你打下了坚实的基础,最重要的下一步是 动手实践!尝试自己扩展这个文章系统,比如增加“编辑”和“删除”功能,或者增加“用户登录”功能,祝你学习愉快!
