对于使用PHP开发的网站来说,MySQL数据库几乎是最常见的数据存储方案之一。新闻文章、用户账号、评论、阅读量以及网站后台设置,都可以通过MySQL保存和读取。
因此,对于刚开始学习PHP的人来说,掌握PHP如何连接MySQL,是进入实际网站开发非常重要的一步。
现代PHP连接MySQL主要有两种方式:PDO和MySQLi。两者都属于目前仍在使用的正规数据库访问方式,也都支持预处理语句。此前PHP中的mysql_*系列函数已经被废弃并最终从PHP中移除,因此新项目不应该再使用诸如mysql_connect()和mysql_query()这样的旧式代码。
准备MySQL数据库
在PHP连接MySQL之前,首先需要确认MySQL服务已经正常运行,并且已经创建了需要使用的数据库。
例如,可以创建一个名为my_database的数据库:
CREATE DATABASE my_database;
实际网站中,还应该为应用程序创建专门的数据库用户,而不是直接使用MySQL的管理员账号。例如:
CREATE USER 'php_user'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON my_database.* TO 'php_user'@'localhost';
这样做的好处是可以把网站程序与数据库管理员权限分开。即使网站程序出现安全问题,也不应该让网站使用的数据库账号拥有整个MySQL服务器的最高权限。
生产环境中,数据库密码也不建议直接写在公开的代码仓库里,更合理的方式是通过配置文件、环境变量或者服务器上的安全配置保存数据库连接信息。
使用MySQLi建立第一个数据库连接
PHP提供的MySQLi扩展专门用于MySQL数据库操作。最简单的连接方式如下:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$conn = new mysqli(
'localhost',
'php_user',
'password',
'my_database'
);
$conn->set_charset('utf8mb4');
} catch (mysqli_sql_exception $e) {
die('数据库连接失败');
}
这里有一个初学者容易忽略的问题:new mysqli()本身并不是默认遇到错误就自动抛出异常。如果希望使用try...catch捕获数据库连接和查询异常,可以通过mysqli_report()开启相应的错误报告模式。
另外,设置:
$conn->set_charset('utf8mb4');
也非常重要。对于中文网站,使用utf8mb4能够更好地处理中文、特殊字符以及Emoji等Unicode字符。
如果连接成功,PHP就已经建立了与MySQL服务器之间的数据库连接。
执行第一条SELECT查询
建立连接以后,就可以执行SQL查询。
例如,假设数据库中存在一个users表:
$sql = "SELECT id, name, email FROM users";
$result = $conn->query($sql);
如果查询成功,$result会返回结果对象。接下来可以逐条读取数据:
while ($row = $result->fetch_assoc()) {
echo "ID: " . $row['id'];
echo ",姓名:" . $row['name'];
echo ",邮箱:" . $row['email'];
echo "
";
}
fetch_assoc()会把当前记录转换成关联数组,因此可以通过数据库字段名访问对应的数据。
例如:
$row['id']
$row['name']
$row['email']
分别对应数据库中的id、name和email字段。
如果查询成功,但是数据库中没有任何记录,并不意味着query()执行失败。对于成功执行的SELECT语句,即使结果集为空,仍然会得到一个结果对象,只是其中没有数据。因此,“没有查询到记录”和“SQL执行失败”是两个完全不同的问题。
为什么不能直接把用户输入拼进SQL
实际网站中,很少会永远查询固定数据。例如,网站可能需要根据用户提交的ID查询文章:
$id = $_GET['id'];
这时候千万不要直接把变量拼接进SQL:
$sql = "SELECT * FROM news WHERE id = $id";
这种写法可能导致SQL注入等安全问题。
更安全的方式是使用预处理语句。
MySQLi的写法如下:
$stmt = $conn->prepare(
"SELECT id, title, content FROM news WHERE id = ?"
);
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['title'];
}
这里的?是参数占位符,真正的数据通过bind_param()传入。
这样,SQL语句结构和用户提供的数据就被分开处理,可以有效降低SQL注入风险。
INSERT、UPDATE和DELETE同样应该使用预处理
如果网站需要保存用户提交的信息,也应该使用预处理语句。
例如向用户表插入姓名和邮箱:
$name = 'Tom';
$email = 'tom@example.com';
$stmt = $conn->prepare(
"INSERT INTO users (name, email) VALUES (?, ?)"
);
$stmt->bind_param("ss", $name, $email);
$stmt->execute();
这里的ss表示两个参数都是字符串。
如果参数是整数,则可以使用i。例如:
$stmt->bind_param("i", $id);
在实际项目中,查询、增加、修改和删除数据库记录,都应该尽量采用这种参数化方式,而不是通过字符串拼接构造SQL。
PHP也可以使用PDO
除了MySQLi,PHP还可以使用PDO连接MySQL。
例如:
$pdo = new PDO(
'mysql:host=localhost;dbname=my_database;charset=utf8mb4',
'php_user',
'password'
);
$pdo->setAttribute(
PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION
);
PDO的优势在于提供了相对统一的数据库访问接口。除了MySQL之外,还可以通过相应驱动连接其他数据库。
如果一个PHP项目确定长期使用MySQL,MySQLi和PDO都可以成为合理选择;如果希望使用统一的数据库抽象接口,PDO通常更加方便。
对于新开发的网站,重要的并不是纠结“PDO还是MySQLi谁绝对更快”,而是选择一种现代数据库接口,并始终坚持使用预处理语句、正确的字符集以及合理的错误处理方式。
查询失败应该如何排查
PHP连接MySQL时,最常见的问题通常集中在几个方面。
如果出现类似:
Access denied for user
首先检查数据库用户名、密码、主机地址以及数据库用户权限。
如果出现:
Unknown database
通常意味着指定的数据库不存在,或者数据库名称写错。
如果SQL执行失败,则需要检查SQL语法、表名、字段名以及当前数据库用户是否拥有相应权限。
开发阶段可以记录详细的数据库异常信息,例如:
try {
// 数据库操作
} catch (mysqli_sql_exception $e) {
error_log($e->getMessage());
die('数据库操作失败');
}
但在正式网站中,不应该直接把完整的数据库错误信息显示给普通访客,因为错误信息可能暴露数据库结构、表名甚至服务器配置。
是否需要主动关闭数据库连接
在普通PHP网站中,一个请求执行结束以后,数据库连接通常会随PHP请求生命周期结束而释放,因此并不是每个简单脚本都必须在最后写:
$conn->close();
不过,如果是长期运行的PHP进程、CLI程序、队列Worker或者其他持续运行的服务,就应该更加重视数据库连接的生命周期和资源管理。
对于普通网站程序,更重要的是不要在一个请求过程中毫无必要地建立大量数据库连接,并且应该把数据库连接代码进行统一管理。
从连接MySQL开始建立良好的代码习惯
PHP连接MySQL看起来只是几行代码,但它实际上涉及网站安全和程序架构中的多个重要问题。
一个规范的数据库操作流程通常包括:建立连接、设置正确的字符集、执行参数化查询、处理结果、捕获异常,并根据业务需要使用事务。
对于初学者来说,最重要的并不是记住某一个函数,而是建立正确的数据库操作习惯。
不要使用已经淘汰的mysql_*函数,不要把用户输入直接拼接到SQL中,不要把数据库管理员账号用于网站程序,也不要把生产环境的数据库密码随意写入公开代码。
掌握这些基本原则之后,再学习PDO、MySQLi、事务、索引和查询优化,PHP数据库开发就会逐渐从“能连接数据库”进入真正的工程实践阶段。
对于一个实际运行的网站来说,PHP连接MySQL只是第一步。真正决定数据库系统是否可靠的,是后面的SQL设计、安全控制、索引规划、错误处理以及整个应用程序的数据访问架构。
PHP 如何连接 MySQL?从数据库连接到执行第一条查询语句
喜欢这篇报道?
使用下面的功能,方便以后继续阅读和分享 MNewsTV
关于文章收藏
收藏不需要注册帐号,收藏信息仅保存在当前浏览器中。
删除收藏请进入「我的收藏」进行管理。
分享 Facebook | X | WhatsApp | LinkedIn
捐助(Paypal): https://www.paypal.me/observeccp 订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP