ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# PHP PDO 教程 > 原文: [https://zetcode.com/php/pdo/](https://zetcode.com/php/pdo/) 在本教程中,我们展示了如何在 PHP PDO 中对数据库进行编程。 ## PHP PDO PHP 数据对象(PDO)定义了用于访问 PHP 中数据库的轻量级接口。 它提供了一个数据访问抽象层,用于在 PHP 中使用数据库。 它定义了用于各种数据库系统的一致 API。 ## PHP PDO 类 `PDO`表示 PHP 与数据库服务器之间的连接。 `PDOStatement`代表准备好的语句,在执行该语句后,代表关联的结果集。 `PDOException`表示 PDO 引发的错误。 ## MySQL 数据库 在本教程中,我们将使用 MySQL 数据库。 `countries_mysql.sql` ```php 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 语句,返回该语句返回的结果集(如果有)。 `version.php` ```php <?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 的版本。 ```php $dsn = "mysql:host=localhost;dbname=mydb"; $user = "user12"; $passwd = "12user"; ``` 这些变量用于创建到数据库的连接字符串。 `dsn`是数据源名称,其中包含连接到数据库所需的信息。 ```php $pdo = new PDO($dsn, $user, $passwd); ``` 创建一个新的`PDO`对象。 我们向构造器传递数据源名称以及用户名和密码。 `PDO`类表示 PHP 与数据库服务器之间的连接。 ```php $stm = $pdo->query("SELECT VERSION()"); ``` `query()`方法在单个函数调用中执行一条 SQL 语句。 它返回结果集。 ```php $version = $stm->fetch(); ``` PDO 语句的`fetch()`方法从结果集中获取下一行。 在我们的例子中,它是 MySQL 的一个版本。 ```php echo $version[0] . PHP_EOL; ``` `$version`是一个数组; 我们得到它的第一个值。 ```php $ php version.php 5.7.22-0ubuntu0.16.04.1 ``` 这是输出。 ## PHP PDO 执行 PDO `exec()`执行一条 SQL 语句并返回受影响的行数。 `affected_rows.php` ```php <?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"; ``` 该代码示例将删除三行。 它打印受影响的行数。 ```php $nrows = $pdo->exec("DELETE FROM countries WHERE id IN (1, 2, 3)"); ``` 在此 SQL 语句中,我们删除 ID 为 1、2 和 3 的行。已删除的行数存储在`$nrows`变量中。 ```php echo "The statement deleted $nrows rows\n"; ``` 我们打印已删除的行数。 ## PHP PDO 提取样式 提取样式参数控制如何将下一行返回给调用方。 例如,`PDO::FETCH_ASSOC`返回按列名索引的数组,`PDO::FETCH_NUM`返回按列号索引的数组,`PDO::FETCH_BOTH`返回按列名和索引列号索引的数组。 默认的获取样式为`PDO::FETCH_BOTH`。 `fetch_style_num.php` ```php <?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"); } ``` 在此代码示例中,我们在索引数组中获取数据。 ```php $stm = $pdo->query("SELECT * FROM countries"); ``` 我们从`countries`表中选择所有数据。 ```php $rows = $stm->fetchAll(PDO::FETCH_NUM); ``` 我们将`PDO:FETCH_NUM`样式传递给`fetchAll()`方法。 ```php foreach($rows as $row) { printf("$row[0] $row[1] $row[2]\n"); } ``` 我们遍历`$rows`数组并打印字段。 通过数组索引访问这些字段。 `fetch_style_assoc.php` ```php <?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"); } ``` 在此示例中,我们以关联数组的形式获取数据。 ```php $rows = $stm->fetchAll(PDO::FETCH_ASSOC); ``` 在`fetchAll()`方法中,我们使用`PDO::FETCH_ASSOC`样式。 ## PHP PDO 参数绑定 SQL 语句通常是动态构建的。 用户提供一些输入,并且此输入已内置到语句中。 每当我们处理来自用户的输入时,我们都必须谨慎。 它具有一些严重的安全隐患。 动态构建 SQL 语句的推荐方法是使用参数绑定。 PDO 包含`bindParam()`和`bindValue()`方法来创建参数化查询。 PDO 允许将数据绑定到问号或命名的占位符。 `parameterized_query.php` ```php <?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()`创建参数化查询。 我们使用问号占位符。 ```php $id = 12; ``` 说此输入来自用户。 ```php $stm = $pdo->prepare("SELECT * FROM countries WHERE id = ?"); $stm->bindValue(1, $id); $stm->execute(); ``` `select`语句从表中获取特定行。 我们将带有`bindValue()`的值绑定到问号占位符。 在第二种情况下,我们使用`bindParam()`。 `parameterized_query2.php` ```php <?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; ``` 该示例选择并打印特定的行。 ```php $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。 `create_table.php` ```php <?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 $ php create_table.php The last inserted row id is: 4 ``` This is the output. ```php 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()`将回滚事务。 `transaction.php` ```php <?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; } ``` 在示例中,我们将两个新的国家/地区添加到数据库表中。 将`insert`语句放置在事务中:要么执行两个插入,要么都不执行。 ```php } catch(Exception $e) { $pdo->rollback(); throw $e; } ``` 如果发生异常,我们回滚事务:没有数据写入数据库。 我们抛出异常,以便异常处理继续按常规方式进行。 ## PHP PDO 获取元数据 元数据是有关数据库中数据的信息。 元数据包含有关我们存储数据的表和列的信息。 SQL 语句影响的行数是元数据。 结果集中返回的行数和列数也是元数据。 `column_count.php` ```php <?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()`方法检索数据库连接属性。 `connection_attributes.php` ```php <?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 $ php connection_attributes.php Driver: mysql Server version: 5.7.22-0ubuntu0.16.04.1 Autocommit mode: 1 ``` 这是一个示例输出。 在以下示例中,我们打印列元数据。 列元数据通过`getColumnMeta()`方法检索。 `column_metadata.php` ```php <?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 $ php column_metadata.php Table name: countries Column name: id Column length: 20 Column flags: not_null primary_key ``` This is a sample output. 您可能也对以下相关教程感兴趣: [PHP SQLite3 教程](/php/sqlite3/), [CakePHP 数据库教程](/php/cakephpdatabase/), [Doctrine `QueryBuilder`教程](/doctrine/querybuilder/), [PHP 文件系统函数](/articles/phpfilesystemfunctions/) , [Twig 教程](/php/twig/), [PHP Faker 教程](/php/faker/), [PHP 教程](/lang/php/)或列出[所有 PHP 教程](/all/#php)。 在本教程中,我们使用 PHP PDO 处理 MySQL 数据库。