下文主要给大家带来PDO与MySQLi各自优势及该如何选择,希望这些内容能够带给大家实际用处,这也是我编辑PDO与MySQLi各自优势及该如何选择这篇文章的主要目的。好了,废话不多说,大家直接看下文吧。
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;
对于以上关于PDO与MySQLi各自优势及该如何选择,大家是不是觉得非常有帮助。如果需要了解更多内容,请继续关注我们的行业资讯,相信你会喜欢上这些内容的。
亿速云「云数据库 MySQL」免部署即开即用,比自行安装部署数据库高出1倍以上的性能,双节点冗余防止单节点故障,数据自动定期备份随时恢复。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。