PHP MySQLi

OOP and procedural APIs, prepared statements, and differences from PDO.

Intermediate
Key Pointsmysqli is MySQL-only but offers `multi_query` and other specifics.

Two APIs

mysqli offers both OOP and procedural interfaces with identical capability. Use OOP in new code.

PHP
<?php
// 面向对象
$mysqli = new mysqli("127.0.0.1", "user", "pass", "demo", 3306);
if ($mysqli->connect_errno) {
    exit("连接失败: " . $mysqli->connect_error);
}
$mysqli->set_charset("utf8mb4");

// 过程式(等价)
$link = mysqli_connect("127.0.0.1", "user", "pass", "demo", 3306);
if (!$link) {
    exit("连接失败: " . mysqli_connect_error());
}
mysqli_set_charset($link, "utf8mb4");

echo "两种方式都连接成功\n";

$mysqli->close();
mysqli_close($link);
Output
两种方式都连接成功
new mysqli(...) does not throw by default; failure only sets connect_errno. Enable mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) — recommended in every project.

Queries

PHP
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$db = new mysqli("127.0.0.1", "user", "pass", "demo");
$db->set_charset("utf8mb4");

$res = $db->query("SELECT id, name FROM users ORDER BY id");

while ($row = $res->fetch_assoc()) {
    echo $row["id"] . " " . $row["name"] . "\n";
}
echo "共 " . $res->num_rows . " 行\n";

$res->free();
$db->close();
Output
1 Tom
2 Amy
3 Bob
共 3 行

Prepared statements

PHP
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$db = new mysqli("127.0.0.1", "user", "pass", "demo");
$db->set_charset("utf8mb4");

$stmt = $db->prepare("SELECT name FROM users WHERE id = ?");
$stmt->bind_param("i", $id);

$id = 2;
$stmt->execute();

$name = null;
$stmt->bind_result($name);
$stmt->fetch();

echo $name, "\n";

$stmt->close();
$db->close();
Output
Amy

The first argument to bind_param is a type string: i, d, s, b. A wrong type does not error but can break comparisons and sorting.

Differences from PDO

AspectmysqliPDO
Databases仅 MySQL12 种驱动
Named params不支持支持
Exceptions需 mysqli_reportERRMODE_EXCEPTION
Fetch stylefetch_assoc 等FETCH_* 常量
Multi querymulti_query不支持(防注入)
Async支持不支持
Class mapping无FETCH_CLASS

multi_query

PHP
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$db = new mysqli("127.0.0.1", "user", "pass", "demo");

$sql = "INSERT INTO users (name, email) VALUES ('X', 'x@e.com');
        INSERT INTO users (name, email) VALUES ('Y', 'y@e.com');";

$db->multi_query($sql);

do {
    if ($res = $db->store_result()) {
        $res->free();
    }
} while ($db->more_results() && $db->next_result());

echo "执行了 " . $db->affected_rows . " 行(最后一条语句)\n";

$db->close();
Output
执行了 1 行(最后一条语句)
multi_query runs several statements at once, so concatenation means full injection. Use it only with fully server-generated SQL.

Common errors

ErrorCauseFix
Commands out of sync上一次结果没 free 就发新查询每次 store_result 后 free
No such file or directorylocalhost 走 socket 且路径错改用 127.0.0.1
中文乱码没 set_charsetset_charset("utf8mb4")
Too many connections连接未关,或并发高用完 close,或上连接池

Friends & Partners