PDO vs. MySQLi: Der Kampf der PHP-Datenbank-APIs

藏色散人
Freigeben: 2023-04-05 17:24:01
Original
2996 Leute haben es durchsucht

PDO vs. MySQLi: Der Kampf der PHP-Datenbank-APIs

Einführung

Die Tage der Verwendung der Erweiterung mysql_ sind vorbei, seit PHP 5.5 Seine Methoden sind ab PHP 7 veraltet und wurden entfernt. Aber das Internet ist immer noch voll von alten Tutorials, die Anfänger einfach kopieren/einfügen und mit älteren PHP-Versionen auf Shared-Hosting-Plattformen verwenden können.

Wenn Sie MySQL oder MariaDB in PHP verwenden, haben Sie jetzt die Möglichkeit, MySQLi oder PDO zu verwenden. Ersteres ist nur eine verbesserte Version, unterstützt prozedurale und OOP und fügt vorbereitete Anweisungen hinzu, während letzteres eine Abstraktionsschicht ist, die es Ihnen ermöglicht, eine einheitliche API für alle 12 unterstützten Datenbanktreiber zu verwenden. Obwohl MySQL die beliebteste Datenbank in der PHP-Welt ist.

Theoretisch benötigen wir nicht für jeden vorhandenen Datenbanktyp eine herstellerspezifische API, da es viel einfacher ist, nur eine zu verwenden. Obwohl daran sicherlich viel Wahres dran ist, besteht das Problem darin, dass PDO_MYSQL nicht über alle neuesten und besten Funktionen verfügt, die MySQLi bietet. Ich verstehe ehrlich gesagt nicht, warum das so ist, da dies jeden Grund für die Verwendung einer herstellerspezifischen API völlig beseitigen würde. Dennoch kann ich mir vorstellen, dass die meisten Menschen diese zusätzlichen Funktionen nicht benötigen, aber es gibt sicherlich einige, die dies tun.

Vorteile von PDO

1. Nützliche Erfassungsmethoden

2. Ermöglichen Sie die direkte Übergabe von Variablen und Werten

3. Möglichkeit, Variablentypen automatisch zu erkennen (was tatsächlich passiert, ist, dass beim Senden an den Server alles als Zeichenfolge behandelt, aber in den richtigen Typ konvertiert wird. Dies funktioniert zu 100 % in vorbereiteten Anweisungen, hat jedoch in einigen Fällen keine Auswirkung in Randfällen, z. B. im Simulationsmodus)

4. Bietet eine Option zum automatischen Puffern von Ergebnissen mithilfe vorbereiteter Anweisungen

5. Benannte Parameter (obwohl das Ausschalten des Simulationsmodus in PDO nutzlos ist, weil Sie (kann nur einmal den gleichen Namen verwenden)

MySQLi-Vorteile

1. Informationen über betroffene Zeilen abrufen Die Möglichkeit, mehr bereitzustellen Informationen, wie z. B. das Aktualisieren von Zeilen mit demselben Wert (kann im PDO als Konstruktor festgelegt und später nicht geändert werden)

3. Korrekte Methode zum Herunterfahren der Datenbank

4. ok, wenn der Simulationsmodus in PDO aktiviert ist)

5. Beständige Verbindungen verwenden, um automatisch zu löschen

Unterschiede im Code

PDO und MySQLi sind sehr ähnlich, haben aber eine leicht unterschiedliche Syntax. MySQLi folgt der alten PHP-Snake_case-Konvention, während PDO camelCase verwendet. Darüber hinaus werden die Methoden von MySQLi als Objekteigenschaften verwendet, während PDO die traditionelle Syntax für Funktionen verwendet.

Sowohl PDO als auch MySQLi machen die Sache komplizierter, da Sie zwei separate Methoden verwenden müssen, um vorbereitete Anweisungen zu verwenden. Durch PDO entfällt jedoch die Notwendigkeit, dedizierte Bindungsfunktionen zu verwenden.

Zum Beispiel können Sie dies in der herstellerspezifischen PostgreSQL-API tun.

Als Referenz finden Sie hier ein Beispiel für die Durchführung einer „nicht vorbereiteten“ Abfrage, um ein assoziatives Array mit MySQLi und PDO zu erhalten.

$arr = $mysqli->query("SELECT * FROM myTable")->fetch_all(MYSQLI_ASSOC);
Nach dem Login kopieren
rrree

Eigentlich ist es am besten, einen Wrapper, einen Abfrage-Builder oder ORM zu verwenden. Obwohl PDO Werte direkt an die Ausführung binden kann, ist dies immer noch nicht ideal. In der von mir erstellten Klasse können Sie alle Aufrufe verketten und dabei Werte als Parameter-Parameterbindungen übergeben.

$arr = $pdo->query("SELECT * FROM myTable")->fetchAll(PDO::FETCH_ASSOC);
Nach dem Login kopieren

Das gesamte assoziative Array wird jetzt übersichtlicher in einer Variablen gespeichert.

Neue Datenbankverbindung erstellen

PDO

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

MySQLi

$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}
Nach dem Login kopieren

Einfügen, aktualisieren, löschen

PDO

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}
Nach dem Login kopieren

MySQLi

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

Beachten Sie, dass Prepare() und Execute() mithilfe von PDO verknüpft werden können.

Anzahl der betroffenen Zeilen abrufen

PDO

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

MySQLi

$stmt->rowCount();
Nach dem Login kopieren

Neuesten Primärschlüssel einfügen

Beachten Sie, dass beide Methoden die Verbindungsvariable verwenden, nicht $stmt.

PDO

$stmt->affected_rows;
Nach dem Login kopieren

MySQLi

$pdo->lastInsertId();
Nach dem Login kopieren

Übereinstimmende Zeilen abrufen

PDO

Im PDO das Einzige implementieren Dies erreichen Sie, indem Sie es als Verbindungsoption festlegen, wodurch sich das Verhalten von rowCount() ändert. Das bedeutet, dass rowCount() übereinstimmende Zeilen oder geänderte Zeilen für die gesamte Datenbankverbindung zurückgibt, jedoch nicht für beide.

$mysqli->insert_id;
Nach dem Login kopieren

MySQLi

$options = [
  PDO::MYSQL_ATTR_FOUND_ROWS => true];
Nach dem Login kopieren

Dadurch wird die gesamte Informationsfolge wie folgt ausgegeben:

$mysqli->info;
Nach dem Login kopieren

Sie können dies tun

Rows matched: 1 Changed: 0 Warnings: 0
Nach dem Login kopieren

Jetzt können Sie einfach auf diese Werte zugreifen . Beachten Sie, dass der Wert eine Zeichenfolge ist, sodass Sie alle Werte in int umwandeln können.

===

funktioniert, oder Sie können == streng überprüfen.

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

Abrufen

Assoziatives Array abrufen

PDO

['Rows matched' => '1', 'Changed' => '0', 'Warnings' => '0']
Nach dem Login kopieren

MySQLi

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

Eine einzelne Zeile abrufen

PDO

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

MySQLi

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

Einen einzelnen Wert (Skalar) abrufen

PDO

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

MySQLi

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

Array von Objekten abrufen

PDO

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

MySQLi

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

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

PDO

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

MySQLi

$search = "%{$_POST[&#39;search&#39;]}%";
$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(&#39;No rows&#39;);
var_export($arr);
$stmt->close();
Nach dem Login kopieren

获取模式

到目前为止,这是我最喜欢的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(&#39;No rows&#39;);
var_export($arr);
$stmt = null;
Copy
Nach dem Login kopieren

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(&#39;No rows&#39;);
var_export($arr);
$stmt->close();
Nach dem Login kopieren

输出:

[&#39;Cool Event&#39; => &#39;Seattle&#39;, &#39;Fun Event&#39; => &#39;Dallas&#39;, &#39;Boring Event&#39; => &#39;Chicago&#39;]
Nach dem Login kopieren

获取组列

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(&#39;No rows&#39;);
var_export($arr);
$stmt = null;
Copy
Nach dem Login kopieren

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(&#39;No rows&#39;);
var_export($arr);
$stmt->close();
Copy
Nach dem Login kopieren

输出:

[
  &#39;blonde&#39; => [&#39;Patrick&#39;, &#39;Olivia&#39;],
  &#39;brunette&#39; => [&#39;Kyle&#39;, &#39;Ricky&#39;],
  &#39;red&#39; => [&#39;Jordan&#39;, &#39;Eric&#39;]
]
Nach dem Login kopieren

获取键/值对数组

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(&#39;No rows&#39;);
var_export($arr);
$stmt = null;
Copy
Nach dem Login kopieren

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(&#39;No rows&#39;);
var_export($arr);
$stmt->close();
Copy
Nach dem Login kopieren

输出:

[
  17 => [&#39;max_bench&#39; => 230, &#39;max_squat&#39; => 175],
  84 => [&#39;max_bench&#39; => 195, &#39;max_squat&#39; => 235],
  136 => [&#39;max_bench&#39; => 135, &#39;max_squat&#39; => 285]
]
Nach dem Login kopieren

获取组

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(&#39;No rows&#39;);
var_export($arr);
$stmt = null;
Copy
Nach dem Login kopieren

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(&#39;No rows&#39;);
var_export($arr);
$stmt->close();
Copy
Nach dem Login kopieren

输出:

[
  &#39;blonde&#39; => [
    [&#39;name&#39; => &#39;Patrick&#39;, &#39;age&#39; => 22],
    [&#39;name&#39; => &#39;Olivia&#39;, &#39;age&#39; => 18]
  ],
  &#39;brunette&#39;  => [
    [&#39;name&#39; => &#39;Kyle&#39;, &#39;age&#39;=> 25],
    [&#39;name&#39; => &#39;Ricky&#39;, &#39;age&#39; => 34]
  ],
   &#39;red&#39;  => [
    [&#39;name&#39; => &#39;Jordan&#39;, &#39;age&#39; => 17],
    [&#39;name&#39; => &#39;Eric&#39;, &#39;age&#39; => 52]
  ]
]
Nach dem Login kopieren

在数组中的位置

PDO

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

MySQLi

$inArr = [12, 23, 44];
$clause = implode(&#39;,&#39;, array_fill(0, count($inArr), &#39;?&#39;)); /
$types = str_repeat(&#39;i&#39;, 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(&#39;No rows&#39;);
var_export($resArr);
$stmt->close();
Nach dem Login kopieren

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

PDO

$inArr = [1, 3, 5];
$clause = implode(&#39;,&#39;, array_fill(0, count($inArr), &#39;?&#39;)); 
$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(&#39;No rows&#39;);
var_export($resArr);
$stmt = null;
Copy
Nach dem Login kopieren

MySQLi

$inArr = [12, 23, 44];
$clause = implode(&#39;,&#39;, array_fill(0, count($inArr), &#39;?&#39;));
$types = str_repeat(&#39;i&#39;, count($inArr));
$types .= &#39;i&#39;; //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(&#39;No rows&#39;);
var_export($resArr);
$stmt->close();
Nach dem Login kopieren

交易

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([&#39;Rick&#39;, &#39;NY&#39;])) throw new Exception(&#39;Stmt 1 Failed&#39;);
  else if(!$stmt2->execute([27, 139])) throw new Exception(&#39;Stmt 2 Failed&#39;);
  $stmt1 = null;
  $stmt2 = null;
  $pdo->commit();
} catch(Exception $e) {
  $pdo->rollback();
  throw $e;
}
Nach dem Login kopieren

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[&#39;name&#39;], $_POST[&#39;age&#39;]);
  $stmt2->bind_param("si", $_POST[&#39;name&#39;], $_SESSION[&#39;id&#39;]);
  $stmt1->execute();
  $stmt2->execute();
  $stmt1->close();
  $stmt2->close();
  $mysqli->autocommit(TRUE);
} catch(Exception $e) {
  $mysqli->rollback(); 
  throw $e;
}
Nach dem Login kopieren

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

命名为Paramters

$stmt = $pdo->prepare("UPDATE myTable SET name = :name WHERE id = :id");
$stmt->execute([&#39;:name&#39; => &#39;David&#39;, &#39;:id&#39; => 3]);
$stmt = null;
Nach dem Login kopieren

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

Das obige ist der detaillierte Inhalt vonPDO vs. MySQLi: Der Kampf der PHP-Datenbank-APIs. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!