ZetCode

PHP mysqli

最后修改于 2025 年 2 月 16 日

PHP mysqli 教程展示了如何使用 mysqli 扩展在 PHP 中进行 MySQL 编程。

MySQL

MySQL 是一个领先的开源数据库管理系统。它是一个多用户、多线程的数据库管理系统。MySQL 在 Web 上尤其流行。它是非常流行的 LAMP 平台的一部分,即 Linux、Apache、MySQL 和 PHP。目前 MySQL 由 Oracle 公司所有。MySQL 数据库可在大多数主流操作系统平台上使用。它运行于 BSD Unix、Linux、Windows 或 Mac OS。

PHP mysqli

MySQLi 扩展(MySQL Improved)是 PHP 脚本语言中使用的关系型数据库驱动程序,用于提供与 MySQL 数据库的接口。它同时提供了面向对象和过程化的 API。与 MySQL 交互的其他方式有:PDO 和 ORM 解决方案。

pdo_mysql PHP 数据对象模块是 PHP 应用程序的数据库抽象层。如果我们编写可移植的数据库 PHP 脚本,这个模块会很有用。

在 PHP 中,也有用于操作 MySQL 的 ORM 解决方案,例如 Doctrine 或 Eloquent。

$ sudo apt install php8.1-mysql

我们安装 php8.1-mysql 模块。安装过程中会创建一个 /etc/php/8.1/mods-available/mysqli.ini 文件,该文件用于启用此扩展。

PHP mysqli 版本

在下面的示例中,我们确定 MySQL 数据库的版本。

version.php
<?php

$con = new mysqli("localhost", "dbuser", "passwd", "mydb");

if ($con->connect_errno) {

    printf("connection failed: %s\n", $con->connect_error());
    exit();
}

$res = $con->query("SELECT VERSION()");

if ($res) {

    $row = $res->fetch_row();
    echo $row[0];
}

$res->close();
$con->close();

该示例打印出 MySQL 的版本。

$con = new mysqli("localhost", "dbuser", "passwd", "mydb");

首先创建一个到数据库的连接。mysqli 类接受主机名、用户名、密码和数据库名作为参数。

if ($con->connect_errno) {

    printf("connection failed: %s\n", $con->connect_error());
    exit();
}

如果连接尝试失败,connect_errno 包含错误代码值。如果没有发生错误,则其值为零。connect_error 方法返回上一个连接错误的字符串描述。

$res = $con->query("SELECT VERSION()");

query 方法在数据库上执行一个查询。SELECT VERSION 语句返回 MySQL 的版本。

if ($res) {

    $row = $res->fetch_row();
    echo $row[0];
}

fetch_row 以枚举数组的形式返回一行结果。我们的结果只包含一个值。

$res->close();
$con->close();

最后,我们释放资源。

$ php version.php
8.0.29-0ubuntu0.22.04.2

mysqli 驱动也支持过程式编程风格。

version2.php
<?php

$con = mysqli_connect("localhost", "dbuser", "passwd", "mydb");

if (mysqli_connect_errno()) {

    printf("connection failed: %s\n", mysqli_connect_error());
    exit();
}

$query = "SELECT VERSION()";

$res = mysqli_query($con, $query);

if ($res) {

    $row = mysqli_fetch_row($res);
    echo $row[0];
}

mysqli_free_result($res);
mysqli_close($con);

该示例使用过程式函数返回 MySQL 的版本。

PHP mysqli 创建表

下面的示例创建一个新的数据库表。表是使用 CREATE TABLE 语句创建的。行是使用 INSERT INTO 语句添加到表中的。

create_table.php
<?php

$host = "localhost";
$user = "dbuser";
$passwd = "passwd";
$db = "mydb";

function execute_query($query, $con)
{
    $res = $con->query($query);

    if (!$res) {

        echo "failed to execute query: $query\n";
    } else {
        echo "Query: $query executed\n";
    }

    if (is_object($res)) {

        $res->close();
    }
}

$con = new mysqli($host, $user, $passwd, $db);

if ($con->connect_errno) {

    printf("connection failed: %s\n", $con->connect_error());
    exit();
}

$query = "DROP TABLE IF EXISTS cars";
execute_query($query, $con);

$query = "CREATE TABLE cars(id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255), price INT)";
execute_query($query, $con);

$query = "INSERT INTO cars(name, price) VALUES('Audi', 52642)";
execute_query($query, $con);

$query = "INSERT INTO cars(name, price) VALUES('Mercedes', 57127)";
execute_query($query, $con);

$query = "INSERT INTO cars(name, price) VALUES('Skoda', 9000)";
execute_query($query, $con);

$query = "INSERT INTO cars(name, price) VALUES('Volvo', 29000)";
execute_query($query, $con);

$query = "INSERT INTO cars(name, price) VALUES('Bentley', 350000)";
execute_query($query, $con);

$query = "INSERT INTO cars(name, price) VALUES('Citroen', 21000)";
execute_query($query, $con);

$query = "INSERT INTO cars(name, price) VALUES('Hummer', 41400)";
execute_query($query, $con);

$query = "INSERT INTO cars(name, price) VALUES('Volkswagen', 21600)";
execute_query($query, $con);

$con->close();

该示例创建了包含八行数据的 cars 表。

PHP mysqli 预处理语句

当我们编写预处理语句时,我们使用占位符而不是直接将值写入语句中。预处理语句可以提高安全性和性能。在 mysqli 中,prepare 函数准备一个 SQL 语句以供执行。

prepared_statement.php
<?php

$host = "localhost";
$user = "dbuser";
$passwd = "passwd";
$db = "mydb";

$con = new mysqli($host, $user, $passwd, $db);

if ($con->connect_errno) {

    printf("connection failed: %s\n", $con->connect_error());
    exit();
}

$id = 3;

$query = "SELECT id, name, price FROM cars WHERE id = ?";

if ($stmt = $con->prepare($query)) {

    $stmt->bind_param('i', $id);

    $stmt->execute();
    $stmt->bind_result($row_id, $name, $price);
    $stmt->fetch();

    echo "$row_id $name $price\n";

    $stmt->close();
} else {

    echo "failed to fetch data\n";
}

$con->close();

该示例从表中选择一个特定的行。它使用了预处理语句。

$query = "SELECT id, name, price FROM cars WHERE id = ?";

当我们编写预处理语句时,我们使用占位符而不是直接将值写入语句中。预处理语句速度更快,并且可以防范 SQL 注入攻击。? 是一个占位符,稍后将被填充。在我们的例子中,我们有一个值:一个整数 id。

$stmt->bind_param('i', $id);

$id 变量的值通过 bind_param 方法绑定到占位符。第一个参数指定变量类型;在我们的例子中是整数。

$stmt->execute();

语句被执行。

$stmt->bind_result($row_id, $name, $price);

bind_result 将返回的值绑定到指定的变量。

echo "$row_id $name $price\n";

我们将变量打印到终端。

$con->close();

我们关闭该语句。

$ php prepared_statement.php
3 Skoda 9000

PHP mysqli fetch_row

fetch_row 方法从结果集中获取一行数据,并将其作为枚举数组返回。每一列都存储在从 0 开始的数组偏移量中。每次后续调用此函数将返回结果集中的下一行,如果没有更多行,则返回 NULL

fetch_rows.php
<?php

$host = "localhost";
$user = "dbuser";
$passwd = "passwd";
$db = "mydb";

$con = new mysqli($host, $user, $passwd, $db);

if ($con->connect_errno) {

    printf("connection failed: %s\n", $con->connect_error());
    exit();
}

$query = "SELECT * FROM cars";

if ($res = $con->query($query)) {

    printf("Select query returned %d rows.\n", $res->num_rows);

    while ($row = $res->fetch_row())
    {
        printf("%s %s %s\n", $row[0], $row[1], $row[2]);
    }

    $res->close();
} else {

    echo "failed to fetch data\n";
}

$con->close();

该示例返回 cars 表中的所有行。

$query = "SELECT * FROM cars";

这个 SELECT 查询选择了表中的所有行。

if ($res = $con->query($query)) {

我们使用 query 方法执行 SELECT 查询。

printf("Select query returned %d rows.\n", $res->num_rows);

返回的行数存储在 num_rows 属性中。

while ($row = $res->fetch_row())
{
    printf("%s %s %s\n", $row[0], $row[1], $row[2]);
}

我们通过在 while 循环中使用 fetch_row 来获取表中的所有行。

$ php fetch_rows.php
Select query returned 8 rows.
1 Audi 52642
2 Mercedes 57127
3 Skoda 9000
4 Volvo 29000
5 Bentley 350000
6 Citroen 21000
7 Hummer 41400
8 Volkswagen 21600

PHP mysqli fetch_assoc

fetch_assoc 返回一个关联数组,其字符串表示结果集中获取的行。数组中的每个键代表结果集列名之一,如果结果集中没有更多行,则返回 NULL

fetch_rows2.php
<?php

$host = "localhost";
$user = "dbuser";
$passwd = "passwd";
$db = "mydb";

$con = new mysqli($host, $user, $passwd, $db);

if ($con->connect_errno) {

    printf("connection failed: %s\n", $con->connect_error());
    exit();
}

$query = "SELECT * FROM cars";

if ($res = $con->query($query)) {

    printf("Select query returned %d rows.\n", $res->num_rows);

    while ($row = $res->fetch_assoc())
    {
        printf("%s %s %s\n", $row['id'], $row['name'], $row['price']);
    }

    $res->close();
} else {

    echo "failed to fetch data\n";
}

$con->close();

该示例返回 cars 表中的所有行。

while ($row = $res->fetch_assoc())
{
    printf("%s %s %s\n", $row['id'], $row['name'], $row['price']);
}

当我们使用 fetch_assoc 时,我们通过数组表示法来引用列。

PHP mysqli fetch_object

fetch_object 返回一个具有字符串属性的对象,这些属性对应于获取的行,如果结果集中没有更多行,则返回 NULL

fetch_rows3.php
<?php

$host = "localhost";
$user = "dbuser";
$passwd = "passwd";
$db = "mydb";

$con = new mysqli($host, $user, $passwd, $db);

if ($con->connect_errno) {

    printf("connection failed: %s\n", $con->connect_error());
    exit();
}

$query = "SELECT * FROM cars";

if ($res = $con->query($query)) {

    printf("Select query returned %d rows.\n", $res->num_rows);

    while ($row = $res->fetch_object())
    {
        printf("%s %s %s\n", $row->id, $row->name, $row->price);
    }

    $res->close();
} else {

    echo "failed to fetch data\n";
}

$con->close();

该示例返回 cars 表中的所有行。

while ($row = $res->fetch_object())
{
    printf("%s %s %s\n", $row->id, $row->name, $row->price);
}

当我们使用 fetch_object 时,我们通过对象访问表示法来引用列。

PHP mysqli 列名

下一个示例打印列名以及来自数据库表的数据。我们将列名称为元数据。

column_names.php
<?php

$host = "localhost";
$user = "dbuser";
$passwd = "passwd";
$db = "mydb";

$con = new mysqli($host, $user, $passwd, $db);

if ($con->connect_errno) {

    printf("connection failed: %s\n", $con->connect_error());
    exit();
}

$query = "SELECT * FROM cars";

if ($res = $con->query($query)) {

    $num_rows = $res->num_rows;
    $num_fields = $res->field_count;

    printf("Select query returned %d rows.\n", $num_rows);
    printf("Select query returned %d columns.\n", $num_fields);

    $fields = $res->fetch_fields();

    while ($row = $res->fetch_row()) {

        for ($i = 0; $i < $num_fields; $i++) {

            echo $fields[$i]->name . ": " . $row[$i] . "\n";
        }

        echo "*******************************\n";
    }

    $res->close();
} else {

    echo "failed to fetch data\n";
}

$con->close();

该示例打印 cars 表的所有行以及列标题。

$num_rows = $res->num_rows;
$num_fields = $res->field_count;

num_rows 属性返回结果中的行数。field_count 返回结果中的字段数。

$fields = $res->fetch_fields();

fetch_fields 方法返回一个对象数组,代表结果集中的字段。这些就是列名。

while ($row = $res->fetch_row()) {

    for ($i = 0; $i < $num_fields; $i++) {

        echo $fields[$i]->name . ": " . $row[$i] . "\n";
    }

    echo "*******************************\n";
}

我们显示列名和数据。

$ php column_names.php
Select query returned 8 rows.
Select query returned 3 columns.
id: 1
name: Audi
price: 52642
*******************************
id: 2
name: Mercedes
price: 57127
*******************************
id: 3
name: Skoda
price: 9000
*******************************
...

来源

MySQL Improved Extension - PHP 手册

这是 PHP mysqli 教程。

作者

我叫 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已经撰写了超过 1400 篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 PHP 教程。