首页 > 数据库 > MySQL > 正文

PDO与MySQLi:PHP数据库API之战

2020-03-22 19:48:35
字体:
来源:转载
供稿:网友

介绍

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

如果你在PHP中使用html' target='_blank'>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之战的详细内容,PHP教程

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表