Mysqli oder PDO - Was sind die Vor- und Nachteile? [geschlossen]

342

An unserer Stelle teilen wir die Verwendung von mysqli und PDO für Dinge wie vorbereitete Anweisungen und Transaktionsunterstützung auf. Einige Projekte verwenden eines, andere das andere. Es ist unwahrscheinlich, dass wir jemals zu einem anderen RDBMS wechseln.

Ich bevorzuge PDO aus dem einzigen Grund, weil es benannte Parameter für vorbereitete Anweisungen zulässt, und soweit ich weiß, ist dies bei mysqli nicht der Fall.

Gibt es andere Vor- und Nachteile bei der Auswahl eines Standards als Standard, wenn wir unsere Projekte konsolidieren, um nur einen Ansatz zu verwenden?

Polsonby
quelle
5
Dieser Artikel hilft bei der Auswahl des zu verwendenden Artikels . Wenn Sie die Leistung in Betracht ziehen, kann dies Ihnen bei der Auswahl helfen.
Ravi404
3
Es ist lustig, wie viele Leute eine Frage, die "nicht konstruktiv" ist, positiv bewertet und bewertet haben. Die Sache ist, der gesamte Thread ist sehr konstruktiv - vielleicht sollten die Moderatoren dies berücksichtigen, wenn sie beurteilen, ob eine Frage konstruktiv ist oder nicht?
Marlar
@marlar Ich stimme dir sooooooo zu! Dies ist in der Tat das größte Problem bei StackOverflow. Ausgezeichnete Fragen / Diskussionen sind immer geschlossen.
Sliq

Antworten:

243

Nun, man könnte mit dem objektorientierten Aspekt, den vorbereiteten Aussagen, der Tatsache, dass es zum Standard wird usw. argumentieren. Aber ich weiß, dass es meistens besser ist, jemanden davon zu überzeugen, mit einem Killer-Feature besser zu funktionieren. Da ist es also:

Eine wirklich schöne Sache mit PDO ist, dass Sie die Daten abrufen und automatisch in ein Objekt einfügen können. Wenn Sie kein ORM verwenden möchten (weil es nur ein schnelles Skript ist), aber die Objektzuordnung mögen, ist es WIRKLICH cool:

class Student {

    public $id;
    public $first_name;
    public $last_name

    public function getFullName() {
        return $this->first_name.' '.$this->last_name
    }
}

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)

    $stmt = $dbh->query("SELECT * FROM students");

    /* MAGIC HAPPENS HERE */

    $stmt->setFetchMode(PDO::FETCH_INTO, new Student);


    foreach($stmt as $student)
    {
        echo $student->getFullName().'<br />';
    } 

    $dbh = null;
}
catch(PDOException $e)
{
    echo $e->getMessage();
}
e-satis
quelle
12
Gibt es einen Unterschied zwischen oben und $mysqliResult->fetch_object("student");?
Andy Fleming
2
@ e-satis nein, ich benutze PHP. Öffentliche Felder verletzen die Kapselung, AS A BEST PRACTICEes ist also nur ... lol :) Google verwendet keine öffentlichen Felder, sondern nur Zugriffsmethoden : google-styleguide.googlecode.com/svn/trunk/… .
OZ_
6
@ e-satis: Entschuldigen Sie das Einspringen, aber Getter und Setter sind erforderlich, wenn Sie steuern möchten, was passiert, wenn die Variablen geändert werden. Andernfalls können Sie den internen Status Ihres Objekts einfach nicht garantieren (dies ist insbesondere dann ein Problem, wenn Sie ein anderes Objekt im Inneren haben). Dies ist völlig sprachunabhängig. @OZ_: Beruhige dich. Persönliche Kritik wird nur jemanden in die Defensive führen.
James P.
2
@monadic: Einverstanden. Die Kapselung ist natürlich ein gültiges Argument, wenn es um Kernkomponenten oder komplexe Objekte usw. geht, jedoch als Repräsentation von Datensätzen, die andernfalls Lese- / Schreibassoziationen wären. Arrays, das ist akzeptabel. Darüber hinaus ermöglicht es eine einfachere Typprüfung, da Datensätze durch das System schweben.
Dan Lugg
15
@outis Ich hoffe, ich bin hier nicht in der Minderheit, aber ich bin nicht der Meinung, dass Antworten nach ihrer Sicherheit gegenüber neuen Entwicklern beurteilt werden sollten. Klingt hart, ist aber wahr. Der Zweck einer Antwort auf SO besteht nicht nur darin, Code zum Kopieren und Einfügen bereitzustellen, sondern auch Verständnis zu vermitteln. Es ist nicht die Aufgabe des Antwortenden, sicherzustellen, dass jede Sicherheitslücke oder jeder Musterfehler in einem Beispiel behandelt wird, da die Anwendung, in die der Code kopiert wird, von Natur aus anders ist als jede andere Anwendung, die denselben Code verwendet.
Mattygabe
57

Das Verschieben einer Anwendung von einer Datenbank in eine andere ist nicht sehr häufig, aber früher oder später arbeiten Sie möglicherweise an einem anderen Projekt mit einem anderen RDBMS. Wenn Sie mit PDO zu Hause sind, gibt es an diesem Punkt mindestens eine Sache weniger zu lernen.

Abgesehen davon finde ich die PDO-API etwas intuitiver und sie fühlt sich wirklich objektorientiert an. mysqli scheint nur eine prozedurale API zu sein, die objektiviert wurde, wenn Sie wissen, was ich meine. Kurz gesagt, ich finde es einfacher, mit PDO zu arbeiten, aber das ist natürlich subjektiv.

Das Ö
quelle
25

Ich habe angefangen, PDO zu verwenden, weil die Anweisungsunterstützung meiner Meinung nach besser ist. Ich verwende eine ActiveRecord-ähnliche Datenzugriffsschicht, und es ist viel einfacher, dynamisch generierte Anweisungen zu implementieren. Die Parameterbindung von MySQLi muss in einem einzigen Funktions- / Methodenaufruf erfolgen. Wenn Sie also erst zur Laufzeit wissen, wie viele Parameter Sie binden möchten, müssen Sie diese verwendencall_user_func_array() (ich glaube, das ist der richtige Funktionsname) für die Auswahl verwenden . Und vergessen Sie die einfache dynamische Ergebnisbindung.

Am allermeisten mag ich PDO, weil es eine sehr vernünftige Abstraktionsebene ist. Es ist einfach, es in vollständig abstrahierten Systemen zu verwenden, in denen Sie kein SQL schreiben möchten, aber es macht es auch einfach, ein optimierteres, reines Abfragetypsystem zu verwenden oder beide zu kombinieren.

Brian Warshaw
quelle
2
Ergebnisbindung mit dynamisch generierten Abfragen ist möglich, wir machen das bei unseren Anwendungen. Es ist jedoch ein großer Schmerz.
Pim Jäger
17

PDO ist der Standard, den die meisten Entwickler erwarten. mysqli war im Wesentlichen eine maßgeschneiderte Lösung für ein bestimmtes Problem, weist jedoch alle Probleme der anderen DBMS-spezifischen Bibliotheken auf. PDO ist der Ort, an dem all die harte Arbeit und das kluge Denken stattfinden werden.

Dave Gregory
quelle
15

Folgendes ist noch zu beachten: Derzeit (PHP 5.2) ist die PDO-Bibliothek fehlerhaft . Es ist voller seltsamer Fehler. Beispiel: Vor dem Speichern von a PDOStatementin einer Variablen sollte die Variable darin bestehen unset(), eine Menge Fehler zu vermeiden. Die meisten davon wurden in PHP 5.3 behoben und werden Anfang 2009 in PHP 5.3 veröffentlicht, das wahrscheinlich viele andere Fehler aufweisen wird. Sie sollten sich auf die Verwendung von PDO für PHP 6.1 konzentrieren, wenn Sie eine stabile Version wünschen, und auf die Verwendung von PDO für PHP 5.3, wenn Sie der Community helfen möchten.

Tom
quelle
2
Ich denke, dass die Vorteile, die PDO bietet, es wert sind, die Fehler zu verstehen und zu umgehen. PHP selbst ist voll von sehr erschwerenden Fehlern, von denen wir einige nicht einmal effizient umgehen können, und bietet dennoch viele Vorteile, die dazu führen, dass wir es anstelle anderer Optionen verwenden.
Brian Warshaw
11
Ähm, seltsam, ich habe nie einen Fehler mit PDO erlebt. Und ich benutze es oft.
NikiC
Mysqli hat auch Fehler. Alle Software hat Fehler.
Bill Karwin
10

Ein weiterer bemerkenswerter (guter) Unterschied zu PDO besteht darin, dass die PDO::quote()Methode automatisch die einschließenden Anführungszeichen hinzufügt, während mysqli::real_escape_string()(und ähnliche) dies nicht tun:

PDO :: quote () setzt Anführungszeichen um die Eingabezeichenfolge (falls erforderlich) und maskiert Sonderzeichen in der Eingabezeichenfolge unter Verwendung eines Anführungsstils, der dem zugrunde liegenden Treiber entspricht.

Alix Axel
quelle
8

PDO erleichtert die Skalierung erheblich, wenn Ihre Site / Web-App wirklich funktioniert, da Sie täglich Master- und Slave-Verbindungen einrichten können, um die Last auf die Datenbank zu verteilen. Außerdem steuert PHP standardmäßig auf PDO um.

PDO Info

Skalieren einer Webanwendung

Dfranc3373
quelle
6

Im Sinne der Ausführungsgeschwindigkeit gewinnt MySQLi, aber wenn Sie keinen guten Wrapper mit MySQLi haben, sind seine Funktionen für vorbereitete Anweisungen schrecklich.

Es gibt immer noch Fehler in meinem, aber wenn jemand es will, hier ist es .

Kurz gesagt, wenn Sie nach einem Geschwindigkeitsgewinn suchen, dann MySQLi; Wenn Sie eine einfache Bedienung wünschen, dann PDO.

Ry-
quelle
2
Könnten Sie im Sinne der Geschwindigkeit Benchmarks geben?
Julius F
8
Jonathen Robson hat unter jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks einen anständigen Geschwindigkeitsvergleich der beiden durchgeführt . Zusammenfassung: inserts - fast gleich, selects - mysqli ist für nicht vorbereitete Anweisungen ~ 2,5% schneller / für vorbereitete Anweisungen ~ 6,7% schneller. Angesichts der geringen Leistungseinbußen PDOüberwiegen die Funktionen und die Flexibilität der Verwendung im Allgemeinen die Leistungseinbußen.
Adam
1
@Adam Danke für den Link zu meinem Blog!
jnrbsn
@ daemonfire300 Dies ist wahr, es sind keine Benchmarks erforderlich. PDO umschließt die mysqli-Bibliothek. Ich würde wahrscheinlich den Fan treffen, wenn jemand beweisen könnte, dass PDO schneller als mysqli ist. :-D
Dyin
@jnrbsn stimmst du Adam zu, was er gesagt hat?
Basit
5

Persönlich benutze ich PDO, aber ich denke, das ist hauptsächlich eine Frage der Präferenz.

PDO verfügt über einige Funktionen, die bei der SQL-Injection helfen ( vorbereitete Anweisungen) ). Wenn Sie jedoch mit Ihrem SQL vorsichtig sind, können Sie dies auch mit mysqli erreichen.

Der Wechsel in eine andere Datenbank ist weniger ein Grund für die Verwendung von PDO. Solange Sie keine "speziellen SQL-Funktionen" verwenden, können Sie von einer Datenbank zu einer anderen wechseln. Sobald Sie jedoch beispielsweise "SELECT ... LIMIT 1" verwenden, können Sie nicht zu MS-SQL wechseln, wo es sich um "SELECT TOP 1 ..." handelt. Das ist also sowieso problematisch.

BlaM
quelle
22
MySQLi hat Anweisungen vorbereitet.
Turm
5

Antwort bearbeitet.

Nach einigen Erfahrungen mit diesen beiden APIs würde ich sagen, dass es zwei Funktionen auf Blockierungsstufe gibt, die mysqli für native vorbereitete Anweisungen unbrauchbar machen.
Sie wurden bereits in 2 ausgezeichneten (aber weit unterschätzten) Antworten erwähnt:

  1. Binden von Werten an eine beliebige Anzahl von Platzhaltern
  2. Rückgabe von Daten als bloßes Array

(beide auch in dieser Antwort erwähnt )

Aus irgendeinem Grund ist mysqli bei beiden gescheitert.
Heutzutage hat es einige Verbesserungen für das zweite ( get_result ) bekommen, aber es funktioniert nur bei mysqlnd-Installationen, was bedeutet, dass Sie sich in Ihren Skripten nicht auf diese Funktion verlassen können.

Dennoch ist es bis heute nicht wertgebunden.

Es gibt also nur eine Wahl: PDO

Alle anderen Gründe, wie z

  • benannte Platzhalter (diese Syntax Zucker ist viel überbewertet)
  • Unterstützung für verschiedene Datenbanken (niemand hat sie jemals benutzt)
  • in Objekt holen (nur nutzloser Syntaxzucker)
  • Geschwindigkeitsunterschied (es gibt keinen)

sind nicht von wesentlicher Bedeutung.

Gleichzeitig fehlen diesen beiden APIs einige wirklich wichtige Funktionen , wie z

  • Bezeichner Platzhalter
  • Platzhalter für die komplexen Datentypen, um die dynamische Bindung weniger mühsam zu machen
  • kürzerer Anwendungscode.

Um die Anforderungen des realen Lebens zu erfüllen, muss eine eigene Abstraktionsbibliothek erstellt werden, die auf einer dieser APIs basiert und manuell analysierte Platzhalter implementiert. In diesem Fall würde ich mysqli bevorzugen, da es einen geringeren Abstraktionsgrad aufweist.

Ihr gesunder Menschenverstand
quelle
Endlich jemand, der die Tatsachen des Lebens kennt und nicht leugnet ...
Ihsan
4

In meinem Benchmark-Skript wird jede Methode 10000 Mal getestet und die Differenz der Gesamtzeit für jede Methode gedruckt. Sie sollten dies in Ihrer eigenen Konfiguration tun, ich bin sicher, dass die Ergebnisse variieren werden!

Das sind meine Ergebnisse:

  • " SELECT NULL" -> PGO()um ~ 0,35 Sekunden schneller
  • " SHOW TABLE STATUS" -> mysqli()um ~ 2,3 Sekunden schneller
  • " SELECT * FROM users" -> mysqli()um ~ 33 Sekunden schneller

Hinweis: Wenn Sie -> fetch_row () für mysqli verwenden, werden die Spaltennamen nicht zum Array hinzugefügt. Ich habe in PGO keine Möglichkeit gefunden, dies zu tun. Aber selbst wenn ich -> fetch_array () verwende, ist mysqli etwas langsamer, aber immer noch schneller als PGO (außer SELECT NULL).

Dobb
quelle
17
Was ist PGO? Und um 33 Sekunden schneller ?! Ich finde das sehr schwer zu glauben ...
Alix Axel
3

Eine Sache, die PDO hat, die MySQLi nicht wirklich mag, ist die Fähigkeit von PDO, ein Ergebnis als Objekt eines bestimmten Klassentyps (z $pdo->fetchObject('MyClass'). B. ) zurückzugeben. MySQLi fetch_object()gibt nur ein stdClassObjekt zurück.

Unbeschriftetes Fleisch
quelle
19
Tatsächlich können Sie eine Klasse manuell angeben: "Objekt mysqli_result :: fetch_object ([Zeichenfolge $ Klassenname [, Array $ Parameter]]"). stdClass wird nur verwendet, wenn Sie nichts angeben.
Andrioid
-4

Es gibt eine Sache zu beachten.

Mysqli unterstützt keine Funktion fetch_assoc (), die die Spalten mit Schlüsseln zurückgibt, die Spaltennamen darstellen. Natürlich ist es möglich, eine eigene Funktion zu schreiben, es ist nicht einmal sehr lang, aber ich hatte wirklich Schwierigkeiten, sie zu schreiben (für Ungläubige: Wenn es Ihnen einfach erscheint, versuchen Sie es einige Zeit selbst und tun Sie es nicht. t betrügen :))

Mike
quelle
4
Hast du das Handbuch ausprobiert? php.net/manual/en/mysqli-result.fetch-assoc.php
Bis
2
Wurde vor längerer Zeit implementiert, aber ja, ich habe das Handbuch überprüft. Funktioniert es mit vorbereiteten Aussagen? Ich bezweifle ...
Mike
2
Eigentlich hat es eine merkwürdig teilweise Unterstützung. Sie können Arrays in regulären Abfragen abrufen, jedoch nicht in parametrisierten Abfragen: -!
Álvaro González
1
Warum nicht eine Antwort löschen, die offensichtlich falsch ist?
Majid Fouladpour
2
@MajidFouladpour - Die Antwort ist nicht offensichtlich falsch . Es fehlt nur ein Kontext. Mysqli unterstützt das Abrufen von assoziativen Arrays nicht vollständig.
Álvaro González