PHP PDO
最后修改于 2025 年 2 月 16 日
在本教程中,我们将展示如何在 PHP PDO 中编程数据库。
PHP PDO
PHP 数据对象 (PDO) 定义了一个轻量级接口,用于在 PHP 中访问数据库。它提供了一个数据访问抽象层,用于在 PHP 中处理数据库。它为使用各种数据库系统定义了一致的 API。
PHP PDO 类
PDO
表示 PHP 与数据库服务器之间的连接。PDOStatement
表示一个预处理语句,并且在语句执行后,会有一个相关的结果集。PDOException
表示 PDO 引发的错误。
MySQL 数据库
在本文中,我们使用 MySQL 数据库。
DROP TABLE IF EXISTS countries; CREATE TABLE countries(id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), population INT); INSERT INTO countries(name, population) VALUES('China', 1382050000); INSERT INTO countries(name, population) VALUES('India', 1313210000); INSERT INTO countries(name, population) VALUES('USA', 324666000); INSERT INTO countries(name, population) VALUES('Indonesia', 260581000); INSERT INTO countries(name, population) VALUES('Brazil', 207221000); INSERT INTO countries(name, population) VALUES('Pakistan', 196626000); INSERT INTO countries(name, population) VALUES('Nigeria', 186988000); INSERT INTO countries(name, population) VALUES('Bangladesh', 162099000); INSERT INTO countries(name, population) VALUES('Nigeria', 186988000); INSERT INTO countries(name, population) VALUES('Russia', 146838000); INSERT INTO countries(name, population) VALUES('Japan', 126830000);
这些 SQL 命令创建一个 countries
表。
PHP PDO 查询
PDO query
在单个函数调用中执行 SQL 语句,返回该语句返回的结果集(如果有)。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $stm = $pdo->query("SELECT VERSION()"); $version = $stm->fetch(); echo $version[0] . PHP_EOL;
该示例返回 MySQL 的版本。
$dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user";
这些变量用于创建到数据库的连接字符串。dsn
是数据源名称,它包含连接到数据库所需的信息。
$pdo = new PDO($dsn, $user, $passwd);
创建一个新的 PDO
对象。我们向构造函数传递数据源名称、用户名和密码。PDO
类表示 PHP 与数据库服务器之间的连接。
$stm = $pdo->query("SELECT VERSION()");
query
方法在单个函数调用中执行 SQL 语句。它返回结果集。
$version = $stm->fetch();
PDO 语句的 fetch
方法从结果集中获取下一行。在我们的例子中,它是 MySQL 的版本。
echo $version[0] . PHP_EOL;
$version
是一个数组;我们获取它的第一个值。
$ php version.php 8.0.29-0ubuntu0.22.04.2
PHP PDO exec
PDO exec
执行 SQL 语句并返回受影响的行数。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $id = 12; $nrows = $pdo->exec("DELETE FROM countries WHERE id IN (1, 2, 3)"); echo "The statement affected $nrows rows\n";
代码示例删除三行。它打印受影响的行数。
$nrows = $pdo->exec("DELETE FROM countries WHERE id IN (1, 2, 3)");
在此 SQL 语句中,我们删除 ID 为 1、2 和 3 的行。已删除的行数存储在 $nrows
变量中。
echo "The statement deleted $nrows rows\n";
我们打印已删除的行数。
PHP PDO fetch 样式
fetch 样式参数控制如何将下一行返回给调用者。例如,PDO::FETCH_ASSOC
返回一个按列名索引的数组,PDO::FETCH_NUM
返回一个按列号索引的数组,而 PDO::FETCH_BOTH
返回一个按列名和索引列号索引的数组。默认的 fetch 样式是 PDO::FETCH_BOTH
。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $stm = $pdo->query("SELECT * FROM countries"); $rows = $stm->fetchAll(PDO::FETCH_NUM); foreach($rows as $row) { printf("$row[0] $row[1] $row[2]\n"); }
在此代码示例中,我们以索引数组的形式获取数据。
$stm = $pdo->query("SELECT * FROM countries");
我们从 countries
表中选择所有数据。
$rows = $stm->fetchAll(PDO::FETCH_NUM);
我们将 PDO:FETCH_NUM
样式传递给 fetchAll
方法。
foreach($rows as $row) { printf("$row[0] $row[1] $row[2]\n"); }
我们遍历 $rows
数组并打印字段。通过数组索引访问字段。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $stm = $pdo->query("SELECT * FROM countries"); $rows = $stm->fetchAll(PDO::FETCH_ASSOC); foreach($rows as $row) { printf("{$row['id']} {$row['name']} {$row['population']}\n"); }
在此示例中,我们将数据提取为关联数组。
$rows = $stm->fetchAll(PDO::FETCH_ASSOC);
在 fetchAll
方法中,我们使用 PDO::FETCH_ASSOC
样式。
PHP PDO 参数绑定
SQL 语句通常是动态构建的。用户提供一些输入,并将此输入构建到语句中。每次我们处理来自用户的输入时,都必须小心。这有一些严重的安全性影响。动态构建 SQL 语句的推荐方法是使用参数绑定。
PDO 包含 bindParam
和 bindValue
方法以创建参数化查询。
PDO 允许将数据绑定到问号或命名占位符。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "root"; $passwd = "andrea"; $pdo = new PDO($dsn, $user, $passwd); $id = 12; $stm = $pdo->prepare("SELECT * FROM countries WHERE id = ?"); $stm->bindValue(1, $id); $stm->execute(); $row = $stm->fetch(PDO::FETCH_ASSOC); echo "Id: " . $row['id'] . PHP_EOL; echo "Name: " . $row['name'] . PHP_EOL; echo "Population: " . $row['population'] . PHP_EOL;
在此示例中,我们使用 bindValue
创建一个参数化查询。我们使用问号占位符。
$id = 12;
假设此输入来自用户。
$stm = $pdo->prepare("SELECT * FROM countries WHERE id = ?"); $stm->bindValue(1, $id); $stm->execute();
select 语句从表中获取特定行。我们使用 bindValue
将值绑定到问号占位符。
在第二种情况下,我们使用 bindParam
。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $id = 12; $stm = $pdo->prepare("SELECT * FROM countries WHERE id = :id"); $stm->bindParam(":id", $id, PDO::PARAM_INT); $stm->execute(); $row = $stm->fetch(PDO::FETCH_ASSOC); echo "Id: " . $row['id'] . PHP_EOL; echo "Name: " . $row['name'] . PHP_EOL; echo "Population: " . $row['population'] . PHP_EOL;
该示例选择并打印特定行。
$stm = $pdo->prepare("SELECT * FROM countries WHERE id = :id"); $stm->bindParam(":id", $id, PDO::PARAM_INT); $stm->execute();
这次我们使用命名占位符 (:id
) 和 bindParam
。
PHP PDO 最后插入的行 ID
PDO lastInsertId
方法返回最后插入的行 ID。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $sql = "CREATE TABLE words(id INT PRIMARY KEY AUTO_INCREMENT, word VARCHAR(255))"; $ret = $pdo->exec($sql); $pdo->exec("INSERT INTO words(word) VALUES ('pen')"); $pdo->exec("INSERT INTO words(word) VALUES ('bum')"); $pdo->exec("INSERT INTO words(word) VALUES ('hum')"); $pdo->exec("INSERT INTO words(word) VALUES ('den')"); $rowid = $pdo->lastInsertId(); echo "The last inserted row id is: $rowid\n";
在此示例中,我们创建一个新表。创建表后,我们使用 lastInsertId
找出最后插入的 ID。
$ php create_table.php The last inserted row id is: 4
mysql> select * from words; +----+------+ | id | word | +----+------+ | 1 | pen | | 2 | bum | | 3 | hum | | 4 | den | +----+------+ 4 rows in set (0.01 sec)
我们验证数据。
PHP PDO 事务
事务是针对一个或多个数据库中的数据进行数据库操作的原子单元。事务中所有SQL语句的效果要么全部提交到数据库,要么全部回滚。
PDO beginTransaction
启动一个新事务。PDO commit
提交事务。而 PDO rollback
回滚事务。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); try { $pdo->beginTransaction(); $stm = $pdo->exec("INSERT INTO countries(name, population) VALUES ('Iraq', 38274000)"); $stm = $pdo->exec("INSERT INTO countries(name, population) VALUES ('Uganda', 37673800)"); $pdo->commit(); } catch(Exception $e) { $pdo->rollback(); throw $e; }
在此示例中,我们向数据库表添加两个新国家/地区。插入语句放在一个事务中:要么执行两个插入操作,要么一个都不执行。
} catch(Exception $e) { $pdo->rollback(); throw $e; }
如果发生异常,我们回滚事务:不会向数据库写入任何数据。我们抛出异常,以便异常处理继续以通常的方式进行。
PHP PDO 获取元数据
元数据是关于数据库中数据的信息。元数据包含有关我们在其中存储数据的表和列的信息。SQL 语句影响的行数是元数据。结果集中返回的行数和列数也是元数据。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $stm = $pdo->query("SELECT name, population FROM countries WHERE id=1"); $ncols = $stm->columnCount(); echo "The result set contains $ncols columns\n";
在此示例中,我们使用 columnCount
方法打印结果集中的列数。
getAttribute
方法检索数据库连接属性。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME); $server_version = $pdo->getAttribute(PDO::ATTR_SERVER_VERSION); $autocommit_mode = $pdo->getAttribute(PDO::ATTR_AUTOCOMMIT); echo "Driver: $driver\n"; echo "Server version: $server_version\n"; echo "Autocommit mode: $autocommit_mode\n";
在此示例中,我们使用 getAttribute
方法获取驱动程序名称、服务器版本和自动提交模式。
$ php connection_attributes.php Driver: mysql Server version: 5.7.22-0ubuntu0.16.04.1 Autocommit mode: 1
在下面的示例中,我们打印列元数据。使用 getColumnMeta
方法检索列元数据。
<?php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; $pdo = new PDO($dsn, $user, $passwd); $stm = $pdo->query("SELECT * FROM countries WHERE id=1"); $col_meta = $stm->getColumnMeta(0); echo "Table name: {$col_meta["table"]}\n"; echo "Column name: {$col_meta["name"]}\n"; echo "Column length: {$col_meta["len"]}\n"; echo "Column flags: {$col_meta["flags"][0]} {$col_meta["flags"][1]} \n";
在此示例中,我们获取列表、名称、长度和标志。
$ php column_metadata.php Table name: countries Column name: id Column length: 20 Column flags: not_null primary_key
来源
在本文中,我们使用 PDO 在 PHP 中编程数据库。
作者
列出所有 PHP 教程。