PHP 链接数据库与基础增删改查(CRUD)操作详解
在 PHP 开发中,数据库交互是 Web 应用的核心能力 —— 无论是用户登录注册、商品数据管理,还是内容发布存储,都需要通过 PHP 与数据库建立连接并执行操作。本文以 MySQL 数据库 为例,从环境准备、数据库连接、基础 CRUD(创建 / 读取 / 更新 / 删除)操作三个维度,手把手教你实现 PHP 与数据库的交互,适合 PHP 初学者快速入门。
一、环境准备:搭建基础开发环境
在编写代码前,需确保本地已配置好以下工具和环境,避免后续出现兼容性或依赖问题。
1.1 核心工具清单
PHP 运行环境 | 解析执行 PHP 代码(如 WAMP、XAMPP、MAMP) | 7.4 及以上(LTS) |
MySQL 数据库 | 提供数据存储服务的关系型数据库 | 5.7 或 8.0 |
代码编辑器 | 编写 PHP 代码(如 VS Code、PhpStorm) | 任意支持 PHP 的编辑器 |
浏览器 / Postman | 测试 Web 接口或 PHP 脚本执行结果 | 最新版本 |
1.2 环境验证
- 启动 PHP 运行环境(如 XAMPP 启动 Apache 和 MySQL)。
- 新建
phpinfo.php文件,写入以下代码并放在 Web 根目录(如 XAMPP 的htdocs文件夹):php运行 - 浏览器访问
http://localhost/phpinfo.php,若能看到 PHP 配置页面,且搜索到mysqli或PDO扩展(默认已启用),说明环境正常。
1.3 提前创建数据库和表
为测试 CRUD 操作,先在 MySQL 中创建示例数据库和表(以「用户表 user」为例):
- 打开 MySQL 管理工具(如 XAMPP 的 phpMyAdmin,访问
http://localhost/phpmyadmin)。 - 执行以下 SQL 创建数据库和表:sql
- 表说明:
utf8mb4编码支持表情符号,create_time自动记录数据插入时间,符合实际开发场景。
二、PHP 链接数据库:两种核心方式
PHP 连接 MySQL 主要有两种方式:MySQLi(MySQL Improved,仅支持 MySQL)和 PDO(PHP Data Objects,支持多数据库)。本文重点讲解 PDO(推荐,兼容性强、支持预处理防 SQL 注入),同时补充 MySQLi 示例。
2.1 封装数据库连接工具类(PDO 方式)
为避免重复编写连接逻辑,封装 DB.php 工具类,统一管理连接配置和资源释放:
php
运行
<?php
/**
* 数据库连接工具类(PDO 方式)
*/
class DB {
// 数据库配置(根据你的本地环境修改)
private static $host = 'localhost'; // 数据库主机(默认 localhost)
private static $dbname = 'php_db'; // 数据库名
private static $username = 'root'; // MySQL 用户名(默认 root)
private static $password = ''; // MySQL 密码(XAMPP 默认空,WAMP 可能为 root)
private static $charset = 'utf8mb4'; // 数据库编码
private static $pdo = null; // 存储 PDO 连接实例(单例模式)
/**
* 获取数据库连接(单例模式,避免重复创建连接)
* @return PDO|null 连接实例
*/
public static function getConnection() {
// 若已存在连接,直接返回
if (self::$pdo !== null) {
return self::$pdo;
}
try {
// PDO 连接字符串格式:mysql:host=主机;dbname=数据库名;charset=编码
$dsn = "mysql:host=" . self::$host . ";dbname=" . self::$dbname . ";charset=" . self::$charset;
// 创建 PDO 实例(第三个参数:数组配置,设置错误模式为异常)
self::$pdo = new PDO($dsn, self::$username, self::$password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 开启异常报错(便于调试)
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC // 默认查询结果为关联数组
]);
echo "数据库连接成功!<br>";
return self::$pdo;
} catch (PDOException $e) {
// 捕获连接异常,输出错误信息并终止脚本
die("数据库连接失败:" . $e->getMessage() . "<br>");
}
}
/**
* 关闭数据库连接(PDO 会自动关闭,手动关闭可选)
*/
public static function closeConnection() {
self::$pdo = null;
echo "数据库连接已关闭!<br>";
}
}
// 测试连接(可选)
// DB::getConnection();
// DB::closeConnection();
?>
2.2 MySQLi 连接示例(备用)
若需使用 MySQLi(面向对象方式),连接代码如下(不推荐,仅作参考):
php
运行
<?php
// MySQLi 连接配置
$host = 'localhost';
$dbname = 'php_db';
$username = 'root';
$password = '';
// 创建连接
$conn = new mysqli($host, $username, $password, $dbname);
// 检查连接错误
if ($conn->connect_error) {
die("连接失败:" . $conn->connect_error);
}
echo "MySQLi 连接成功!<br>";
// 关闭连接
$conn->close();
?>
三、基础 CRUD 操作实现(PDO 方式)
以下所有操作均基于 DB.php 工具类,通过 PDO 预处理语句执行 SQL(防 SQL 注入),并封装成可复用的函数。
3.1 新增操作(Create):插入用户数据
需求:向 user 表插入一条用户数据(username=「李四」,age=28,email=「lisi@xxx.com」)。
实现代码(create_user.php):
php
运行
<?php
// 引入数据库连接类
require_once 'DB.php';
/**
* 新增用户
* @param string $username 用户名
* @param int $age 年龄
* @param string $email 邮箱
* @return bool|int 成功返回用户ID,失败返回false
*/
function createUser($username, $age, $email) {
try {
$pdo = DB::getConnection();
// SQL 插入语句(:username 是命名占位符,更易读)
$sql = "INSERT INTO user (username, age, email) VALUES (:username, :age, :email)";
// 准备预处理语句
$stmt = $pdo->prepare($sql);
// 绑定参数(或直接在 execute 中传入关联数组)
$params = [
':username' => $username,
':age' => $age,
':email' => $email
];
// 执行 SQL(返回 bool 值)
$result = $stmt->execute($params);
if ($result) {
// 返回新增用户的自增 ID
return $pdo->lastInsertId();
}
return false;
} catch (PDOException $e) {
echo "新增用户失败:" . $e->getMessage() . "<br>";
return false;
}
}
// 测试新增操作
$userId = createUser("李四", 28, "lisi@xxx.com");
if ($userId) {
echo "新增用户成功!用户ID:" . $userId . "<br>";
} else {
echo "新增用户失败!<br>";
}
// 关闭连接(可选)
DB::closeConnection();
?>
验证结果:访问 http://localhost/create_user.php,若输出「新增用户成功!用户 ID:1」,则在 phpMyAdmin 中查看 user 表,可看到新增的记录。
3.2 查询操作(Read):查询用户数据
需求:两种常见查询场景:
- 单条查询:根据
id查询指定用户。 - 批量查询:查询所有用户或符合条件的用户。
3.2.1 单条查询(按 ID 查询)
php
运行
<?php
require_once 'DB.php';
/**
* 根据 ID 查询用户
* @param int $id 用户ID
* @return array|false 成功返回用户数组,失败返回false
*/
function getUserById($id) {
try {
$pdo = DB::getConnection();
$sql = "SELECT id, username, age, email, create_time FROM user WHERE id = :id";
$stmt = $pdo->prepare($sql);
// 绑定参数(int 类型,可选指定参数类型)
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
// 获取单条结果(关联数组)
$user = $stmt->fetch();
return $user ? $user : false;
} catch (PDOException $e) {
echo "查询用户失败:" . $e->getMessage() . "<br>";
return false;
}
}
// 测试查询(查询 ID=1 的用户)
$user = getUserById(1);
if ($user) {
echo "查询到的用户:<br>";
echo "ID:" . $user['id'] . "<br>";
echo "用户名:" . $user['username'] . "<br>";
echo "年龄:" . $user['age'] . "<br>";
echo "邮箱:" . $user['email'] . "<br>";
echo "创建时间:" . $user['create_time'] . "<br>";
} else {
echo "未查询到该用户!<br>";
}
DB::closeConnection();
?>
3.2.2 批量查询(查询所有用户)
php
运行
<?php
require_once 'DB.php';
/**
* 查询所有用户
* @return array 用户列表数组(空数组表示无数据)
*/
function getAllUsers() {
try {
$pdo = DB::getConnection();
$sql = "SELECT id, username, age, email, create_time FROM user ORDER BY id DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute();
// 获取所有结果(关联数组)
$users = $stmt->fetchAll();
return $users;
} catch (PDOException $e) {
echo "查询所有用户失败:" . $e->getMessage() . "<br>";
return [];
}
}
// 测试批量查询
$userList = getAllUsers();
if (!empty($userList)) {
echo "查询到 " . count($userList) . " 个用户:<br>";
foreach ($userList as $user) {
echo "ID:" . $user['id'] . ",用户名:" . $user['username'] . ",邮箱:" . $user['email'] . "<br>";
}
} else {
echo "暂无用户数据!<br>";
}
DB::closeConnection();
?>
3.3 更新操作(Update):修改用户数据
需求:将 id=1 的用户年龄修改为 30,邮箱修改为「lisi_update@xxx.com」。
实现代码(update_user.php):
php
运行
<?php
require_once 'DB.php';
/**
* 更新用户信息
* @param int $id 用户ID
* @param array $data 要更新的字段(如 ['age' => 30, 'email' => 'xxx'])
* @return bool 成功返回true,失败返回false
*/
function updateUser($id, $data) {
try {
$pdo = DB::getConnection();
// 拼接更新字段(动态生成 SET 部分,避免字段固定)
$updateFields = [];
foreach ($data as $key => $value) {
$updateFields[] = "$key = :$key";
}
$sql = "UPDATE user SET " . implode(', ', $updateFields) . " WHERE id = :id";
$stmt = $pdo->prepare($sql);
// 合并参数(更新字段 + ID)
$params = array_merge($data, ['id' => $id]);
$result = $stmt->execute($params);
// 返回受影响的行数(>0 表示更新成功)
return $stmt->rowCount() > 0;
} catch (PDOException $e) {
echo "更新用户失败:" . $e->getMessage() . "<br>";
return false;
}
}
// 测试更新操作(修改 age 和 email)
$updateData = [
'age' => 30,
'email' => **********'
];
$isSuccess = updateUser(1, $updateData);
if ($isSuccess) {
echo "更新用户成功!<br>";
} else {
echo "更新用户失败(可能 ID 不存在或数据未变更)!<br>";
}
DB::closeConnection();
?>
3.4 删除操作(Delete):删除用户数据
需求:删除 id=1 的用户数据。
实现代码(delete_user.php):
php
运行
<?php
require_once 'DB.php';
/**
* 根据 ID 删除用户
* @param int $id 用户ID
* @return bool 成功返回true,失败返回false
*/
function deleteUser($id) {
try {
$pdo = DB::getConnection();
$sql = "DELETE FROM user WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
// 返回受影响的行数(>0 表示删除成功)
return $stmt->rowCount() > 0;
} catch (PDOException $e) {
echo "删除用户失败:" . $e->getMessage() . "<br>";
return false;
}
}
// 测试删除操作
$isSuccess = deleteUser(1);
if ($isSuccess) {
echo "删除用户成功!<br>";
} else {
echo "删除用户失败(可能 ID 不存在)!<br>";
}
DB::closeConnection();
?>
四、常见问题与注意事项
- 连接失败排查:确认 MySQL 已启动(XAMPP 中检查 MySQL 服务状态)。检查 DB.php 中的 username 和 password 是否与本地 MySQL 配置一致(XAMPP 默认为 root/ 空,WAMP 可能为 root/root)。若报错「Unknown database 'php_db'」,需先手动创建数据库或执行创建数据库的 SQL。
- SQL 注入防护:严禁直接拼接用户输入到 SQL 中(如 $sql = "SELECT * FROM user WHERE username = '$username'"),恶意用户可通过输入 ' OR 1=1 # 绕过验证。必须使用 PDO 预处理语句(prepare + execute),通过占位符(:name 或 ?)绑定参数,PDO 会自动转义特殊字符,彻底防 SQL 注入。
- 编码问题(中文乱码):数据库创建时指定 utf8mb4 编码(支持中文和表情)。PDO 连接字符串中添加 charset=utf8mb4(已在 DB.php 中配置)。网页输出时设置编码:header("Content-Type: text/html; charset=utf-8");。
- 错误调试技巧:PDO 开启 ERRMODE_EXCEPTION 后,可通过 try-catch 捕获异常,输出 $e->getMessage() 查看具体错误(如 SQL 语法错误、字段名错误)。测试脚本时,先单独执行 SQL(如在 phpMyAdmin 中),确认 SQL 正确后再写入 PHP 代码。
- 资源释放:PDO 连接会在脚本执行结束后自动关闭,手动调用 closeConnection() 仅作规范,非必需。预处理语句($stmt)执行后无需手动关闭,脚本结束后自动释放。
五、进阶方向
本文讲解的是 PHP 原生 PDO 操作,实际开发中可通过框架简化代码:
- Laravel:PHP 主流框架,内置 Eloquent ORM,无需编写 SQL 即可实现 CRUD(如
User::create($data)、User::find($id))。 - ThinkPHP:国内常用框架,提供
Db类封装,支持链式操作(如Db::table('user')->where('id', 1)->update($data))。 - Medoo:轻量级数据库框架(仅 1 个文件),适合小型项目,简化 PDO 冗余代码。
若你已掌握本文的基础操作,可进一步学习这些框架,提升开发效率;同时建议了解「事务处理」「分页查询」「联表查询」等进阶功能,应对复杂业务场景。
至此,PHP 链接数据库与基础 CRUD 操作已全部讲解完毕。建议动手实践每一步,遇到报错时对照「常见问题」排查,逐步理解 PHP 与数据库交互的核心逻辑。
s6fr9.hsd-stone.com
xm3t6.hsd-stone.com
1aa5k.hsd-stone.com
ww7j7.hsd-stone.com
31szl.hsd-stone.com
bwajx.hsd-stone.com
ewk3n.hsd-stone.com
i26zn.hsd-stone.com
j607t.hsd-stone.com
p62s7.hsd-stone.com
m7ip4.hsd-stone.com
1s2tn.hsd-stone.com
fd5ig.hsd-stone.com
tx9z0.hsd-stone.com
ryow1.hsd-stone.com
hrhyt.hsd-stone.com
da3pr.hsd-stone.com
nxjih.hsd-stone.com
4g4lu.hsd-stone.com
53t9l.hsd-stone.com

