各类知识收集,PHP技术分享与解决方案各类知识收集,PHP技术分享与解决方案各类知识收集,PHP技术分享与解决方案

Str Tom,为分享PHP技术和解决方案,贡献一份自己的力量!
收藏本站(不迷路),每天更新好文章!
当前位置:首页 > CMS教程 > PHP

PDO与MySQLi:PHP数据库API之战

管理员 2023-09-05
PHP
117

PDO与MySQLi:PHP数据库API之战

内容导读

收集整理的这篇技术教程文章主要介绍了PDO与MySQLi:PHP数据库API之战,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含12667字,纯文字阅读大概需要19分钟

内容图文

介绍

使用mysql_扩展的日子已经过去了,因为自PHP 5.5以来它的方法已被弃用,并且从PHP 7开始被删除。但是互联网上仍然充斥着大量的旧教程,初学者只需复制/粘贴并在共享主机平台上使用旧版本的PHP即可。

如果你在PHP中使用MySQL或MariaDB,那么你现在可以选择MySQLi或PDO。前者只是一个改进版本,支持过程化和OOP,并添加了预处理语句,而后者是一个抽象层,允许你为它支持的所有12个数据库驱动程序使用统一的API。尽管MySQL是PHP世界中最流行的数据库。

理论上,我们不需要为存在的每种数据库类型都提供特定于供应商的API,因为只使用一种数据库要简单得多。虽然对此肯定有很多道理,但问题是PDO_MYSQL并没有MySQLi所具有的所有最新和最先进的特性。老实说,我不明白为什么会这样,因为这将完全消除使用特定于供应商的API的任何理由。尽管如此,我想大多数人并不需要这些额外的功能,但肯定有一些人需要。

PDO的优势

1.有用的获取方式

2.允许直接将变量和值传递给execute

3.能够自动检测变量类型(实际发生的情况是,发送到服务器时,所有内容都被视为字符串,但被转换为正确的类型。这在预处理语句中100%有效,但在某些边缘情况下无效,比如在模拟模式中。)

4.提供一个选项,使用预处理语句自动缓冲结果

5.命名参数(尽管在PDO中关闭模拟模式是无用的,因为你只能使用相同的名称一次)

MySQLi优势

1.异步查询

2.获取有关受影响行的更多信息的能力,比如更新具有相同值的行(可以在PDO中作为构造函数设置完成,以后无法更改)

3.正确的数据库关闭方法

4.一次多个查询(如果在PDO中打开模拟模式,则可以)

5.使用持久连接自动清除

代码的差异

PDO和MySQLi非常相似,但是在语法上略有不同。MySQLi遵循旧式的PHP snake_case约定,而PDO使用camelCase。此外,MySQLi的方法被用作对象属性,而PDO对函数使用传统语法。

PDO和MySQLi都要求你使用两个单独的方法来使用预处理语句,从而使事情变得复杂。不过PDO消除了使用专用绑定函数的需要。

例如,在特定于供应商的PostgreSQL API中,你可以这样做。

下面是一个示例,演示如何执行一个“non-prepared”查询来获取一个包含MySQLi和PDO的关联数组,以供参考。

$arr = $mysqli->query("SELECT * FROM myTable")->fetch_all(MYSQLI_ASSOC);
$arr = $pdo->query("SELECT * FROM myTable")->fetchAll(PDO::FETCH_ASSOC);

实际上,最好的方法是使用包装器、查询生成器或ORM。虽然PDO可以直接将值绑定到execute中,但它仍然不是理想的。在我创建的类中,你可以链接所有调用,同时传入值作为参数参数绑定。

$arr = $mysqli->query("SELECT * FROM myTable WHERE id > ?", [12])->fetchAll('assoc');

现在,在变量中以更简洁的方式存储了整个关联数组。

创建一个新的数据库连接

PDO

$dsn = "mysql:host=localhost;dbname=myDatabase;charset=utf8mb4";$options = [  PDO::ATTR_EMULATE_PREPARES   => false, // turn off emulation mode for "real" prepared statements  PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION, //turn on errors in the form of exceptions  PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, //make the default fetch be an associative array];try {  $pdo = new PDO($dsn, "username", "password", $options);} catch (Exception $e) {  error_log($e->getMessage());  exit('Something weird happened'); //something a user can understand}

MySQLi

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);try {  $mysqli = new mysqli("localhost", "username", "password", "databaseName");  $mysqli->set_charset("utf8mb4");} catch(Exception $e) {  error_log($e->getMessage());  exit('Error connecting to database'); //Should be a message a typical user could understand}

插入、更新、删除

PDO

$stmt = $pdo->prepare("INSERT INTO myTable (name, age) VALUES (?, ?)");$stmt->execute([$_POST['name'], 29]);$stmt = null;

MySQLi

$stmt = $mysqli->prepare("UPDATE myTable SET name = ? WHERE id = ?");$stmt->bind_param("si", $_POST['name'], $_SESSION['id']);$stmt->execute();$stmt->close();

注意,使用PDO可以将prepare()和execute()链接起来。

获取受影响的行数

PDO

$stmt->rowCount();

MySQLi

$stmt->affected_rows;

插入最新的主键

注意,这两种方法都使用connection变量,而不是$stmt。

PDO

$pdo->lastInsertId();

MySQLi

$mysqli->insert_id;

得到匹配的行

PDO

在PDO中,实现这一点的唯一方法是将其设置为一个连接选项,以更改rowCount()的行为。这意味着rowCount()将为整个数据库连接返回匹配的行或更改的行,但不能同时返回两者。

$options = [  PDO::MYSQL_ATTR_FOUND_ROWS => true];

MySQLi

$mysqli->info;

这将输出整个字符串的信息,如:

Rows matched: 1 Changed: 0 Warnings: 0

可以这样做

preg_match_all('/(S[^:]+): (d+)/', $mysqli->info, $matches); $infoArr = array_combine ($matches[1], $matches[2]);var_export($infoArr);

现在可以很容易地访问这些值。注意,该值是一个字符串,因此你可以将所有值转换为int,===可以使用,也可以严格检查==

['Rows matched' => '1', 'Changed' => '0', 'Warnings' => '0']

抓取

获取关联数组

PDO

$stmt = $pdo->prepare("SELECT * FROM myTable WHERE id <= ?");$stmt->execute([5]);$arr = $stmt->fetchAll(PDO::FETCH_ASSOC);if(!$arr) exit('No rows');var_export($arr);$stmt = null;

MySQLi

$stmt = $mysqli->prepare("SELECT id, name, age FROM myTable WHERE name = ?");$stmt->bind_param("s", $_POST['name']);$stmt->execute();$arr = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);if(!$arr) exit('No rows');var_export($arr);$stmt->close();

获取单行

PDO

$stmt = $pdo->prepare("SELECT id, name, age FROM myTable WHERE name = ?");$stmt->execute([$_POST['name']]);$arr = $stmt->fetch(PDO::FETCH_ASSOC);if(!$arr) exit('No rows');var_export($arr);$stmt = null;

MySQLi

$stmt = $mysqli->prepare("SELECT id, name, age FROM myTable WHERE name = ?");$stmt->bind_param("s", $_POST['name']);$stmt->execute();$arr = $stmt->get_result()->fetch_assoc();if(!$arr) exit('No rows');var_export($arr);$stmt->close();

获取单个值(标量)

PDO

$stmt = $pdo->prepare("SELECT id, name, age FROM myTable WHERE name = ?");$stmt->execute([$_POST['name']]);$arr = $stmt->fetch(PDO::FETCH_COLUMN);if(!$arr) exit('No rows');var_export($arr);$stmt = null;

MySQLi

$stmt = $mysqli->prepare("SELECT id, name, age FROM myTable WHERE name = ?");$stmt->bind_param("s", $_POST['name']);$stmt->execute();$arr = $stmt->get_result()->fetch_row()[0];if(!$arr) exit('No rows');var_export($arr);$stmt->close();

获取对象数组

PDO

class myClass {}$stmt = $pdo->prepare("SELECT name, age, weight FROM myTable WHERE name = ?");$stmt->execute(['Joe']);$arr = $stmt->fetchAll(PDO::FETCH_CLASS, 'myClass');if(!$arr) exit('No rows');var_export($arr);$stmt = null;

MySQLi

class myClass {}$arr = [];$stmt = $mysqli->prepare("SELECT id, name, age FROM myTable WHERE id = ?");$stmt->bind_param("s", $_SESSION['id']);$stmt->execute();$result = $stmt->get_result();while($row = $result->fetch_object('myClass')) {  $arr[] = $row;}if(!$arr) exit('No rows');var_export($arr);$stmt->close();

正如你所看到的,PDO在这里非常出色。MySQLi没有像$mysqli_result->fetch_all(MYSQLI_OBJ)这样的东西。PDO甚至更进一步,通过使用fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'myClass')对它进行位元化,以处理在类构造函数之后调用它的默认行为。可以在MySQLi中复制这种行为,但是它依赖于省略构造函数,和魔术方法 _set(),或者只在构造函数中设置它(如果它不等于默认值)。

PDO

$search = "%{$_POST['search']}%";$stmt = $pdo->prepare("SELECT id, name, age FROM myTable WHERE name LIKE ?");$stmt->execute([$search]);$arr = $stmt->fetchAll();if(!$arr) exit('No rows');var_export($arr);$stmt = null;Copy

MySQLi

$search = "%{$_POST['search']}%";$stmt = $mysqli->prepare("SELECT id, name, age FROM myTable WHERE name LIKE ?"); $stmt->bind_param("s", $search);$stmt->execute();$arr = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);if(!$arr) exit('No rows');var_export($arr);$stmt->close();

获取模式

到目前为止,这是我最喜欢的PDO特性。PDO中的获取模式非常有用,而MySQLi还没有添加它们。

获取键/值对

PDO

$stmt = $pdo->prepare("SELECT event_name, location FROM events WHERE id < ?");$stmt->execute([25]);$arr = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);if(!$arr) exit('No rows');var_export($arr);$stmt = null;Copy

MySQLi

$arr = [];$id = 25;$stmt = $con->prepare("SELECT event_name, location FROM events WHERE id < ?");$stmt->bind_param("i", $id);$stmt->execute();$result = $stmt->get_result();while($row = $result->fetch_row()) {  $arr[$row[0]] = $row[1];}if(!$arr) exit('No rows');var_export($arr);$stmt->close();

输出:

['Cool Event' => 'Seattle', 'Fun Event' => 'Dallas', 'Boring Event' => 'Chicago']

获取组列

PDO

$stmt = $pdo->prepare("SELECT hair_color, name FROM myTable WHERE id < ?");$stmt->execute([10]);$arr = $stmt->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_COLUMN);if(!$arr) exit('No rows');var_export($arr);$stmt = null;Copy

MySQLi

$arr = [];$id = 10;$stmt = $con->prepare("SELECT hair_color, name FROM myTable WHERE id < ?");$stmt->bind_param("i", $id);$stmt->execute();$result = $stmt->get_result();while($row = $result->fetch_row()) {  $arr[$row[0]][] = $row[1];}if(!$arr) exit('No rows');var_export($arr);$stmt->close();Copy

输出:

[  'blonde' => ['Patrick', 'Olivia'],  'brunette' => ['Kyle', 'Ricky'],  'red' => ['Jordan', 'Eric']]

获取键/值对数组

PDO

$stmt = $pdo->prepare("SELECT id, max_bench, max_squat FROM myTable WHERE weight < ?");$stmt->execute([200]);$arr = $stmt->fetchAll(PDO::FETCH_UNIQUE);if(!$arr) exit('No rows');var_export($arr);$stmt = null;Copy

MySQLi

$arr = [];$weight = 200;$stmt = $con->prepare("SELECT id, max_bench, max_squat FROM myTable WHERE weight < ?");$stmt->bind_param("i", $weight);$stmt->execute();$result = $stmt->get_result();$firstColName = $result->fetch_field_direct(0)->name;while($row = $stmtResult->fetch_assoc()) {  $firstColVal = $row[$firstColName];  unset($row[$firstColName]);  $arr[$firstColVal] = $row;}if(!$arr) exit('No rows');var_export($arr);$stmt->close();Copy

输出:

[  17 => ['max_bench' => 230, 'max_squat' => 175],  84 => ['max_bench' => 195, 'max_squat' => 235],  136 => ['max_bench' => 135, 'max_squat' => 285]]

获取组

PDO

$stmt = $pdo->prepare("SELECT hair_color, name, age FROM myTable WHERE id < ?");$stmt->execute([12]);$arr = $stmt->fetchAll(PDO::FETCH_GROUP);if(!$arr) exit('No rows');var_export($arr);$stmt = null;Copy

MySQLi

$arr = [];$id = 12;$stmt = $con->prepare("SELECT hair_color, name, age FROM myTable WHERE id < ?");$stmt->bind_param("i", $id);$stmt->execute();$result = $stmt->get_result();$firstColName = $result->fetch_field_direct(0)->name;while($row = $stmtResult->fetch_assoc()) {  $firstColVal = $row[$firstColName];  unset($row[$firstColName]);  $arr[$firstColVal][] = $row;}if(!$arr) exit('No rows');var_export($arr);$stmt->close();Copy

输出:

[  'blonde' => [    ['name' => 'Patrick', 'age' => 22],    ['name' => 'Olivia', 'age' => 18]  ],  'brunette'  => [    ['name' => 'Kyle', 'age'=> 25],    ['name' => 'Ricky', 'age' => 34]  ],   'red'  => [    ['name' => 'Jordan', 'age' => 17],    ['name' => 'Eric', 'age' => 52]  ]]

在数组中的位置

PDO

$inArr = [1, 3, 5];$clause = implode(',', array_fill(0, count($inArr), '?')); $stmt = $pdo->prepare("SELECT * FROM myTable WHERE id IN ($clause)");$stmt->execute($inArr);$resArr = $stmt->fetchAll();if(!$resArr) exit('No rows');var_export($resArr);$stmt = null;Copy

MySQLi

$inArr = [12, 23, 44];$clause = implode(',', array_fill(0, count($inArr), '?')); /$types = str_repeat('i', count($inArr)); /$stmt = $mysqli->prepare("SELECT id, name FROM myTable WHERE id IN ($clause)");$stmt->bind_param($types, ...$inArr);$stmt->execute();$resArr = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);if(!$resArr) exit('No rows');var_export($resArr);$stmt->close();

与其他占位符一起排列的位置

PDO

$inArr = [1, 3, 5];$clause = implode(',', array_fill(0, count($inArr), '?')); $stmt = $pdo->prepare("SELECT * FROM myTable WHERE id IN ($clause) AND id < ?");$fullArr = array_merge($inArr, [5]); $stmt->execute($fullArr);$resArr = $stmt->fetchAll();if(!$resArr) exit('No rows');var_export($resArr);$stmt = null;Copy

MySQLi

$inArr = [12, 23, 44];$clause = implode(',', array_fill(0, count($inArr), '?'));$types = str_repeat('i', count($inArr));$types .= 'i'; //add 1 more int type$fullArr = array_merge($inArr, [26]); $stmt = $mysqli->prepare("SELECT id, name FROM myTable WHERE id IN ($clause) AND age > ?");$stmt->bind_param($types, ...$fullArr); $stmt->execute();$resArr = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);if(!$resArr) exit('No rows');var_export($resArr);$stmt->close();

交易

PDO

try {  $pdo->beginTransaction();  $stmt1 = $pdo->prepare("INSERT INTO myTable (name, state) VALUES (?, ?)");  $stmt2 = $pdo->prepare("UPDATE myTable SET age = ? WHERE id = ?");  if(!$stmt1->execute(['Rick', 'NY'])) throw new Exception('Stmt 1 Failed');  else if(!$stmt2->execute([27, 139])) throw new Exception('Stmt 2 Failed');  $stmt1 = null;  $stmt2 = null;  $pdo->commit();} catch(Exception $e) {  $pdo->rollback();  throw $e;}

MySQLi

try {  $mysqli->autocommit(FALSE);  $stmt1 = $mysqli->prepare("INSERT INTO myTable (name, age) VALUES (?, ?)");  $stmt2 = $mysqli->prepare("UPDATE myTable SET name = ? WHERE id = ?");  $stmt1->bind_param("si", $_POST['name'], $_POST['age']);  $stmt2->bind_param("si", $_POST['name'], $_SESSION['id']);  $stmt1->execute();  $stmt2->execute();  $stmt1->close();  $stmt2->close();  $mysqli->autocommit(TRUE);} catch(Exception $e) {  $mysqli->rollback();   throw $e;}

MySQLi有一个问题,但是解决方案是使用全局处理程序将错误转换为异常。

命名为Paramters

$stmt = $pdo->prepare("UPDATE myTable SET name = :name WHERE id = :id");$stmt->execute([':name' => 'David', ':id' => 3]);$stmt = null;

相关推荐:《mysql教程》《PHP教程》

以上就是PDO与MySQLi:PHP数据库API之战的详细内容,更多请关注Gxl网其它相关文章!

内容总结

以上是为您收集整理的PDO与MySQLi:PHP数据库API之战全部内容,希望文章能够帮你解决PDO与MySQLi:PHP数据库API之战所遇到的程序开发问题。 如果觉得技术教程内容还不错,欢迎将网站推荐给程序员好友。

内容备注

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

扫码关注

qrcode

QQ交谈

回顶部