Was ist das?
Dies ist eine Liste häufig gestellter Fragen zu PHP-Datenobjekten
Warum ist das?
Da PDO einige Funktionen hat, die einem normalen PHP-Benutzer unbekannt sind, sind Fragen zu vorbereiteten Anweisungen und Fehlerbehandlung in PDO ziemlich häufig. Dies ist also nur ein Ort, an dem sie alle zu finden sind.
Was soll ich hier tun?
Wenn Ihre Frage mit dieser Liste eng abgestimmt wurde, finden Sie Ihre Frage unten und wenden Sie die Korrektur auf Ihren Code an. Es ist auch eine gute Idee, einen kurzen Blick auf andere Fragen zu werfen, um sich auf andere häufige Fallstricke vorzubereiten.
Die Liste
- Die PDO-Abfrage schlägt fehl, aber ich kann keine Fehler sehen. Wie erhalte ich eine Fehlermeldung von PDO?
- Wie kann ich vorbereitete Anweisungen mit dem LIKE-Operator verwenden?
- Wie kann ich eine vorbereitete Anweisung für den IN()-Operator erstellen?
- Kann ich eine vorbereitete PDO-Anweisung verwenden, um einen Bezeichner (einen Tabellen- oder Feldnamen) oder ein Syntaxschlüsselwort zu binden?
- Die vorbereitete PDO-Anweisung verursacht einen Fehler in der LIMIT-Anweisung
Siehe auch
- Referenz – Was bedeutet dieses Symbol in PHP?
- Referenz – Was bedeutet dieser Fehler in PHP?
- Referenz – Was ist der Gültigkeitsbereich von Variablen, auf welche Variablen kann von wo aus zugegriffen werden und was sind „undefinierte Variablen“-Fehler?
Die PDO-Abfrage schlägt fehl, aber ich kann keine Fehler sehen. Wie erhalte ich eine Fehlermeldung von PDO?
Um Datenbankfehler sehen zu können, muss man setzen PDO-Fehlermodus zu Ausnahmen. Ausnahmen sind in vielerlei Hinsicht besser als normale Fehler: Sie enthalten immer einen Stack-Trace, sie können mit try..catch abgefangen oder mit einem dedizierten Error-Handler behandelt werden. Und selbst wenn sie nicht behandelt werden, fungieren sie als reguläre PHP-Fehler, die alle wichtigen Informationen liefern und den seitenweiten Einstellungen für die Fehlerberichterstattung folgen.
Beachten Sie, dass die Einstellung dieses Modus als Verbindungsoption dazu führt, dass PDO auch Ausnahmen bei Verbindungsfehlern auslöst, was sehr wichtig ist.
Hier ist also ein Beispiel für die richtige Erstellung einer PDO-Verbindung:
$dsn = "mysql:host=$host;dbname=$db;charset=utf8";
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// other options
);
$pdo = new PDO($dsn, $user, $pass, $opt);
Auf diese Weise verbunden, werden Sie immer über alle Datenbankfehler benachrichtigt, die während der Abfrageausführung aufgetreten sind. Beachten Sie, dass Sie PHP-Fehler im Allgemeinen sehen können müssen. Auf einer Live-Site müssen Sie in die Fehlerprotokolle schauen, also müssen die Einstellungen angepasst werden
error_reporting(E_ALL);
ini_set('display_errors',0);
ini_set('log_errors',1);
Auf einem lokalen Entwicklungsserver ist es in Ordnung, Fehler auf dem Bildschirm zu machen:
error_reporting(E_ALL);
ini_set('display_errors',1);
und natürlich sollten Sie niemals den Fehlerunterdrückungsoperator (@
) vor Ihren PDO-Anweisungen.
Auch aufgrund vieler schlechter Beispiele, die Ihnen sagen, dass Sie jede PDO-Anweisung einschließen sollen try..catch
Block, muss ich deutlich anmerken:
Verwenden Sie den try..catch-Operator NICHT nur, um eine Fehlermeldung anzuzeigen. Nicht erfasste Ausnahmen eignen sich bereits hervorragend für diesen Zweck, da sie sich genauso verhalten wie andere PHP-Fehler. Sie können das Verhalten also mithilfe von Site-weiten Einstellungen definieren. Sie erhalten Ihre Fehlermeldung ohne diesen nutzlosen Code. Eine bedingungslos wiederholte Fehlermeldung kann zwar einem potenziellen Angreifer einige sensible Informationen offenbaren, einen ehrlichen Besucher jedoch verwirren.
- EIN benutzerdefinierter Ausnahmehandler können nachträglich hinzugefügt werden, sind aber nicht erforderlich. Besonders für neue Benutzer empfiehlt es sich, unbehandelte Ausnahmen zu verwenden, da sie äußerst informativ, hilfreich und sicher sind.
- Verwenden
try..catch
nur dann, wenn Sie den Fehler selbst behandeln – sagen wir, um eine Transaktion rückgängig zu machen.
Die vorbereitete PDO-Anweisung verursacht einen Fehler in der LIMIT-Klausel
Aus Kompatibilitätsgründen wird PDO nur emulieren, nacheifern vorbereitete Anweisungen, indem Platzhalter durch tatsächliche Daten ersetzt werden, anstatt sie separat an den Server zu senden, sofern nicht anders angegeben. Und mit “fauler” Bindung (mit Array in execute()) behandelt PDO jeden Parameter als String. Als Ergebnis die vorbereitet LIMIT ?,?
Abfrage wird LIMIT '10', '10'
Dies ist eine ungültige Syntax, die dazu führt, dass die Abfrage fehlschlägt.
Auch dieses Problem kann gelöst werden
-
indem Sie den Emulationsmodus ausschalten (da MySQL alle Platzhalter richtig sortieren kann):
$conn->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
-
durch explizites Binden und Setzen des richtigen Typs (PDO::PARAM_INT):
$stm = $pdo->prepare('SELECT * FROM table LIMIT ?, ?');
$stm->bindValue(1, $limit_from,PDO::PARAM_INT);
$stm->bindValue(2, $per_page,PDO::PARAM_INT);
$stm->execute();
$data = $stm->fetchAll();
Wie kann ich vorbereitete Anweisungen mit dem LIKE-Operator verwenden?
Vorbereitete Erklärung darstellen kann nur vollständiges Datenliteral. Kein Teil von Literal, kein komplexer Ausdruck oder Bezeichner. Aber entweder Nur Zeichenfolge oder Zahl. Eine sehr häufige Falle ist also eine Abfrage wie diese:
$sql = "SELECT * FROM t WHERE column LIKE '%?%'";
Wenn Sie ein wenig über diese Abfrage nachdenken, werden Sie verstehen, dass ein Fragezeichen innerhalb einfacher Anführungszeichen zu einem wörtlichen Fragezeichen wird, ohne eine besondere Bedeutung für die vorbereiteten Anweisungen.
Man muss also ein vollständiges String-Literal mit einer vorbereiteten Anweisung senden. Es gibt 2 Möglichkeiten:
-
entweder zuerst den VOLLSTÄNDIGEN Ausdruck vorbereiten:
$name = "%$name%";
$stm = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");
$stm->execute(array($name));
$data = $stm->fetchAll();
-
oder verwenden Sie eine Verkettung innerhalb der Abfrage
$sql = "SELECT * FROM t WHERE column LIKE concat('%',?,'%')";
obwohl letzteres zu aufgebläht erscheint.
Ich denke, das passt nicht zu SO. Dies ist keine FAQ-Seite. Sie könnten es auf Ihrer Website platzieren. Zumindest die Posts sollten den Besitzer auf “Community-Wiki” ändern
– hek2mgl
13. April 2013 um 18:14 Uhr
Ich finde es sehr überraschend, dass ein 3-jähriger Benutzer mit 52.000 Wiederholungen so etwas mit 5 seiner eigenen Antworten postet. Sie haben genug Repräsentanten, um das PDO-Tag-Wiki zu bearbeiten. Das gehört da hin. Downvotes überall. Markierung zum Schließen.
– Jo Frambach
13. April 2013 um 19:55 Uhr
Haben Sie etwas dagegen, den Eigentümer dieser Frage und aller Antworten auf das Community-Wiki zu ändern? Genau dafür ist CW gedacht.
– Jo Frambach
13. April 2013 um 20:04 Uhr
Zu Ihrer Information, diese Frage wird derzeit unter diskutiert meta.stackexchange.com/questions/176417/…
– Bart
13. April 2013 um 21:14 Uhr
Aufgeteilt in einzelne Beiträge, stelle ich mir vor, dass diese Fragen äußerst nützlich wären. Ich unterstütze die Bemühungen, kanonische oder “Master”-Fragen zu erstellen, aber ich muss zustimmen, dass eine Gruppe wie diese nicht in das Format von SO passt, genauso wie es nicht der Fall wäre, wenn alle diese Fragen von einer Person in einem Beitrag gestellt worden wären eigentlich auf der Suche nach der Antwort.
– jscs
14. April 2013 um 18:21 Uhr