在PHP编程的世界里,mysqli(MySQL Improved Extension)是个非常重要的部分,尤其是在与MySQL数据库交互的时候。今天我就来给大家详细讲讲关于mysqli的方方面面,从基础的连接数据库,到执行查询,再到一些高级用法以及可能遇到的坑。
mysqli是什么
mysqli是PHP中的一个扩展,专门用于与MySQL数据库进行交互。它提供了面向对象和过程式两种编程风格的接口。这就方便了不同编程习惯的开发者们。如果你之前接触过PHP连接MySQL的旧方式,你会发现mysqli在安全性、性能以及功能上都有很多的改进。
连接数据库
1. 过程式风格
要使用mysqli连接数据库,首先得包含它。这很简单,就像下面这样:
<?php
// 引入mysqli扩展
require_once('mysqli.php');
// 定义数据库连接参数
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$dbname = "your_database_name";
// 创建连接
$conn = mysqli_connect($servername, $username, $password, $dbname);
// 检查连接是否成功
if (!$conn) {
die("连接失败: ". mysqli_connect_error());
}
echo "连接成功";
?>
这里最容易出错的地方就是参数的填写。比如说,如果你不小心写错了用户名或者密码,那么就会导致连接失败。并且如果你的MySQL服务器没有正确安装或者配置,也会出现连接问题。这个时候就要仔细检查错误信息,像上面代码中的mysqli_connect_error()这个函数就会返回具体的连接错误信息。例如,可能会提示“Access denied for user 'your_username'@'localhost' (using password: YES)”,这就说明用户名或者密码有错。还有的时候如果提示“Can't connect to MySQL server on 'localhost' (111)”,那可能是MySQL服务没有启动或者服务器IP有问题。
2. 面向对象风格
面向对象风格相对来说可能看起来更清晰一点,对于熟悉面向对象编程的开发者来说可能更容易理解和维护。
<?php
// 创建连接对象
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("连接失败: ". $conn->connect_error);
}
?>
在面向对象风格中,检查连接错误的方式和过程式有点不同,这里是通过$conn->connect_error来获取错误信息的。这两种风格其实在功能上是等同的,你可以根据自己的喜好和项目需求来选择使用哪一种。
执行简单查询
当我们成功连接到数据库之后,就可以执行查询了。比如说我们想从一个叫做“users”的表中查询所有的用户信息。
<?php
// 连接数据库 (前面已经展示了连接代码,这里假设已经连接成功,$conn为连接对象)
// 写一个查询语句
$sql = "SELECT FROM users";
// 执行查询
$result = mysqli_query($conn, $sql);
// 检查查询结果是否有返回值
if ($result) {
// 输出数据
while ($row = mysqli_fetch_assoc($result)) {
print_r($row);
}
} else {
die("查询失败: ". mysqli_error($conn));
}
// 关闭连接
mysqli_close($conn);
?>
这里的mysqli_query函数执行查询操作,如果执行成功则返回一个结果集。然后我们通过mysqli_fetch_assoc函数在while循环中来逐个获取结果集里的行数据并输出。如果查询失败,就像我们在上面的代码中做的一样,我们可以通过mysqli_error函数来获取具体的查询失败的原因。比如说可能是表名写错了“SELECT FROM user(少了s)”,那么就会得到一个类似“Table 'your_database_name.user' doesn't exist”这样的错误提示。
<?php
// 执行查询
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
}
} else {
die("查询失败: ". $conn->error);
}
// 关闭连接
$conn->close();
?>
在面向对象风格中,执行查询是通过连接对象的query方法来进行的,获取查询结果集的操作也和过程式略有不同,不过功能是一样的。
插入数据
在处理数据库操作的时候,插入数据也是非常常见的操作。
假设我们有一个名为“users”的表,里面有“name”、“email”和“password”几个字段,我们要插入一条新的用户数据。
<?php
// 准备要插入的数据
$name = "John Doe";
$email = "johndoe@example.com";
$password = "123456";
// 构建插入语句
$sql = "INSERT INTO users (name, email, password) VALUES ('$name', '$email', '$password')";
// 执行插入操作
if (mysqli_query($conn, $sql)) {
echo "新记录插入成功";
} else {
die("插入失败: ". mysqli_error($conn));
}
// 关闭连接
?>
这里有一个很容易忽略但是很重要的安全风险。直接把变量拼接到SQL语句中的这种方式容易受到SQL注入攻击。比如说,如果恶意用户在“name”字段输入一个值“'; DROP TABLE users; --”,那么就可能会导致你的“users”表被删除。后面我们会讲到如何解决这个问题。
<?php
if ($conn->query($sql) === TRUE) {
} else {
die("插入失败: ". $conn->error);
}
// 关闭连接
?>
防止SQL注入攻击(使用预处理语句)
在前面插入数据的时候我们提到了SQL注入攻击的风险,这里我们就来讲讲如何利用mysqli的预处理语句来防止这种风险。
<?php
// 创建预处理语句
$stmt = mysqli_prepare($conn, "INSERT INTO users (name, email, password) VALUES (?,?,?)");
// 绑定参数
mysqli_stmt_bind_param($stmt, "sss", $name, $email, $password);
if (mysqli_stmt_execute($stmt)) {
} else {
die("插入失败: ". mysqli_stmt_error($stmt));
}
// 关闭预处理语句和连接
mysqli_stmt_close($stmt);
?>
这里通过mysqli_prepare函数创建了一个预处理语句,然后使用mysqli_stmt_bind_param函数将参数绑定到这个语句中。注意这里的“sss”表示我们后面要绑定的三个参数的数据类型都是字符串类型。如果参数的数据类型不同,这个类型标识就要相应的改变。例如,如果有一个整数类型的参数,就可能是“isi”(假设第一个参数是整数类型)。
<?php