Beim Zugriff auf eine Datenbank in PHP haben wir zwei Möglichkeiten: MySQLi und PDO. Was sollten Sie wissen, bevor Sie sich für eines entscheiden? Die Unterschiede, Datenbankunterstützung, Stabilität und Leistung werden in diesem Artikel beschrieben.
Wenn Sie häufig mit Datenbanken in PHP arbeiten, sollten Sie die nützlichen Skripts und Apps für MySQLi und PDO auf Envato Market überprüfen.
PDO-Apps auf dem Envato MarketPDO | MySQLi | |
Datenbank-Unterstützung | 12 verschiedene Fahrer | Nur MySQL |
API | OOP | OOP + verfahrenstechnisch |
Verbindung | Einfach | Einfach |
Benannte Parameter | Ja | Nein |
Objektzuordnung | Ja | Ja |
Vorbereitete Anweisungen (clientseitig) | Ja | Nein |
Performance | Schnell | Schnell |
Gespeicherte Prozeduren | Ja | Ja |
Es ist ein Kinderspiel, mit beiden eine Verbindung zu einer Datenbank herzustellen:
// PDO $ pdo = neues PDO ("mysql: host = localhost; Datenbankname = Datenbank", "Benutzername", "Kennwort"); // mysqli, prozeduraler Weg $ mysqli = mysqli_connect ('localhost', 'username', 'password', 'database'); // mysqli, objektorientiert $ mysqli = new mysqli ('localhost', 'username', 'password', 'database');
Bitte beachten Sie, dass diese Verbindungsobjekte / -ressourcen im Rest dieses Lernprogramms als vorhanden betrachtet werden.
Sowohl PDO als auch MySQLi bieten eine objektorientierte API, MySQLi bietet jedoch auch eine prozedurale API, die Neuankömmlingen das Verständnis erleichtert. Wenn Sie mit dem nativen PHP-MySQL-Treiber vertraut sind, wird die Migration zur prozeduralen MySQLi-Benutzeroberfläche wesentlich einfacher. Sobald Sie jedoch PDO beherrschen, können Sie es mit jeder gewünschten Datenbank verwenden!
Der Hauptvorteil von PDO gegenüber MySQLi liegt in der Unterstützung der Datenbanktreiber. Zum Zeitpunkt dieses Schreibens, PDO unterstützt 12 verschiedene Treiber, im Gegensatz zu MySQLi, das unterstützt Nur MySQL.
Verwenden Sie den folgenden Code, um eine Liste aller Treiber zu drucken, die derzeit von PDO unterstützt werden:
var_dump (PDO :: getAvailableDrivers ());
Was bedeutet das? In Situationen, in denen Sie Ihr Projekt wechseln müssen, um eine andere Datenbank zu verwenden, macht PDO den Prozess transparent. So alles was du tun musst Ändern Sie die Verbindungszeichenfolge und einige Abfragen, wenn sie Methoden verwenden, die von Ihrer neuen Datenbank nicht unterstützt werden. Mit MySQLi müssen Sie dies tun Schreiben Sie jeden Codeblock neu - Abfragen enthalten.
Dies ist eine weitere wichtige Funktion der PDO. Bindungsparameter sind wesentlich einfacher als mit der numerischen Bindung:
$ params = array (': username' => 'test', ': email' => $ mail, ': last_login' => time () - 3600); $ pdo-> vorbereiten ('SELECT * FROM Benutzer WHERE Benutzername =: Benutzername AND Email =: Email AND Last_login>: Last_login'); $ pdo-> ausführen ($ params);
… Im Gegensatz zu MySQLi:
$ query = $ mysqli-> vorbereiten ('SELECT * FROM Benutzer WO Benutzername =? UND E-Mail =? AND last_login>?'); $ query-> bind_param ('sss', 'test', $ mail, time () - 3600); $ Abfrage-> Ausführen ();
Die Bindung der Fragezeichenparameter erscheint zwar kürzer, ist jedoch bei weitem nicht so flexibel wie benannte Parameter, da der Entwickler dies immer tun muss Verfolgen Sie die Reihenfolge der Parameter; es fühlt sich unter Umständen "hackig" an.
Unglücklicherweise, MySQLi unterstützt keine benannten Parameter.
Sowohl PDO als auch MySQLi können Ergebnisse Objekten zuordnen. Dies ist praktisch, wenn Sie keine benutzerdefinierte Datenbank-Abstraktionsebene verwenden möchten, aber dennoch ORM-ähnliches Verhalten wünschen. Stellen wir uns vor, wir hätten eine Nutzer
Klasse mit einigen Eigenschaften, die mit Feldnamen aus einer Datenbank übereinstimmen.
Klasse Benutzer public $ id; public $ first_name; public $ last_name; public function info () return '#'. $ this-> id. ':'. $ this-> first_name. ". $ this-> last_name;
Ohne Objektzuordnung müssten wir den Wert jedes Feldes (entweder manuell oder über den Konstruktor) ausfüllen, bevor wir das verwenden können Info()
Methode richtig.
Dies ermöglicht uns, diese Eigenschaften vor der Konstruktion des Objekts vorzugeben! Zum Beispiel:
$ query = "SELECT ID, Vorname, Nachname VON Benutzern"; // PDO $ result = $ pdo-> Abfrage ($ Abfrage); $ result-> setFetchMode (PDO :: FETCH_CLASS, 'User'); while ($ user = $ result-> fetch ()) echo $ user-> info (). "\ n"; // MySQLI, Verfahrensweise if ($ result = mysqli_query ($ mysqli, $ query)) while ($ user = mysqli_fetch_object ($ result, 'user')) echo $ user-> info (). "\ N "; // MySQLi, Objektorientiert if ($ result = $ mysqli-> query ($ query)) while ($ user = $ result-> fetch_object ('user')) echo $ user-> info () . "\ n";
Beide Bibliotheken bieten SQL-Injection-Sicherheit, sofern der Entwickler sie so verwendet, wie sie beabsichtigt waren (gelesen: Fluchtung / Parameterbindung mit vorbereiteten Anweisungen).
Nehmen wir an, ein Hacker versucht, schädliches SQL über den HTTP-Abfrageparameter "username" (GET) einzuspeisen:
$ _GET ['username'] = "'; DELETE FROM Benutzer; / *"
Wenn dies nicht möglich ist, wird es in die Abfrage "as is" eingefügt - alle Zeilen werden aus der Zeile gelöscht Benutzer
table (sowohl PDO als auch mysqli unterstützen mehrere Abfragen).
// PDO, "manuell" escaping $ username = PDO :: quote ($ _ GET ['username']); $ pdo-> query ("SELECT * FROM Benutzer WO Benutzername = $ Benutzername"); // mysqli, "manual" escaping $ username = mysqli_real_escape_string ($ _ GET ['username']); $ mysqli-> query ("SELECT * FROM Benutzer WHERE Benutzername = '$ Benutzername'");
Wie du siehst, GU :: quote ()
Es entgeht nicht nur dem String, sondern zitiert ihn auch. Auf der anderen Seite, mysqli_real_escape_string ()
wird nur der Zeichenfolge entkommen; Sie müssen die Anführungszeichen manuell anwenden.
// PDO, vorbereitete Anweisung $ pdo-> prepare ('SELECT * FROM Benutzer WHERE username =: username'); $ pdo-> ausführen (array (': username' => $ _GET ['username'])); // mysqli, vorbereitete Anweisungen $ query = $ mysqli-> prepare ('SELECT * FROM Benutzer WHERE username =?'); $ query-> bind_param ('s', $ _GET ['username']); $ Abfrage-> Ausführen ();
Ich empfehle Ihnen, vorbereitete Anweisungen immer mit gebundenen Abfragen anstelle von P zu verwenden
DO :: quote ()
undmysqli_real_escape_string ()
.
Während sowohl PDO als auch MySQLi recht schnell sind, ist MySQLi in Benchmarks unwesentlich schneller - ~ 2,5% für nicht vorbereitete Anweisungen und ~ 6,5% für vorbereitete. Die native MySQL-Erweiterung ist jedoch noch schneller als beide. Wenn Sie also wirklich jede Leistung abschneiden müssen, ist dies eine Sache, die Sie in Betracht ziehen könnten.
Letztendlich gewinnt die PDO diesen Kampf mit Leichtigkeit. Durch die Unterstützung von zwölf verschiedenen Datenbanktreibern (achtzehn verschiedene Datenbanken!) Und benannten Parametern können wir den geringen Leistungsverlust ignorieren und uns an seine API gewöhnen. Unter Sicherheitsaspekten sind beide sicher, solange der Entwickler sie so verwendet, wie sie verwendet werden sollen (gelesen: vorbereitete Anweisungen)..
Wenn Sie also immer noch mit MySQLi arbeiten, ist es vielleicht Zeit für eine Änderung!