Wie kann ich ein PDO-Objekt für eine parametrisierte SELECT-Abfrage richtig verwenden?

85

Ich habe versucht, die PHP.net-Anweisungen zum Ausführen von SELECTAbfragen zu befolgen , bin mir jedoch nicht sicher, wie ich dies am besten tun soll.

Ich möchte SELECT, wenn möglich, eine parametrisierte Abfrage verwenden, um die IDin einer Tabelle zurückzugeben, in der das nameFeld mit dem Parameter übereinstimmt. Dies sollte eine zurückgeben, IDda diese eindeutig ist.

Ich würde das dann gerne IDfür eine INSERTin eine andere Tabelle verwenden, also muss ich feststellen, ob es erfolgreich war oder nicht.

Ich habe auch gelesen, dass Sie die Abfragen für die Wiederverwendung vorbereiten können, war mir aber nicht sicher, wie dies hilft.

Joe Phillips
quelle

Antworten:

158

Sie wählen Daten wie folgt aus:

$db = new PDO("...");
$statement = $db->prepare("select id from some_table where name = :name");
$statement->execute(array(':name' => "Jimbo"));
$row = $statement->fetch(); // Use fetchAll() if you want all results, or just iterate over the statement, since it implements Iterator

Sie fügen auf die gleiche Weise ein:

$statement = $db->prepare("insert into some_other_table (some_id) values (:some_id)");
$statement->execute(array(':some_id' => $row['id']));

Ich empfehle, dass Sie PDO so konfigurieren, dass bei einem Fehler Ausnahmen ausgelöst werden. Sie erhalten dann eine, PDOExceptionwenn eine der Abfragen fehlschlägt - Sie müssen nicht explizit prüfen. Um Ausnahmen zu aktivieren, rufen Sie dies direkt nach dem Erstellen des $dbObjekts auf:

$db = new PDO("...");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
troelskn
quelle
Ich nehme an, Sie meinen PDOStatement, wo Sie ein neues PDO haben (...), richtig?
Joe Phillips
1
Nein. PDO ist die Verbindungsklasse (hätte wahrscheinlich stattdessen PdoConnection heißen sollen). Die Verbindung kann PdoStatements erstellen. Sie rufen setAttribute () für das Verbindungsobjekt auf - nicht für die einzelnen Anweisungen. (Alternativ können Sie es an den Konstruktor übergeben)
troelskn
1
Dies könnte nützlich sein:$db = new PDO('mysql:dbname=your_database;host=localhost', 'junior', '444');
Junior Mayhé
2
$statement->execute(array(':name' => "Jimbo"));Können Sie für die Zeile den Jimbo-Teil erklären?
muttley91
1
@rar In der vorherigen Zeile wird die Abfrage mit einem Platzhalter initiiert :name. Der Aufruf executeerfolgt hier mit einem assoziativen Array von Platzhalter -> Wertepaaren. In diesem Fall wird der :namePlatzhalter durch die Zeichenfolge Jimbo ersetzt. Beachten Sie, dass nicht nur ein String ersetzt wird, da der Wert entweder maskiert oder über einen anderen Kanal als die eigentliche Abfrage gesendet wird, wodurch jegliche Art von Injection-Angriffen verhindert wird.
Troelskn
16

Ich habe in letzter Zeit mit PDO gearbeitet und die obige Antwort ist völlig richtig, aber ich wollte nur dokumentieren, dass das Folgende auch funktioniert.

$nametosearch = "Tobias";
$conn = new PDO("server", "username", "password");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $conn->prepare("SELECT `id` from `tablename` WHERE `name` = :name");
$sth->bindParam(':name', $nametosearch);
// Or sth->bindParam(':name', $_POST['namefromform']); depending on application
$sth->execute();
SmashCode
quelle
16
Nein, dies ist nicht der Fall, da Sie nicht ausgewählt haben, welche Datenbank verwendet werden soll.
Rápli András
3
Das sollte eigentlich in der "Server" -String sein, die eigentlich ein DSN in Form von "{driver}: dbname = {db_name}; host = {server}" sein sollte, wobei die geschweiften
Klammerwerte
12

Sie können die Methoden bindParamoder bindValueverwenden, um Ihre Aussage vorzubereiten. Dies macht die Dinge auf den ersten Blick klarer, anstatt dies zu tun. $check->execute(array(':name' => $name));Insbesondere, wenn Sie mehrere Werte / Variablen binden.

Überprüfen Sie das klare, leicht lesbare Beispiel unten:

$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname LIMIT 1");
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname',  'Bloggs');
$q->execute();

if ($q->rowCount() > 0){
    $check = $q->fetch(PDO::FETCH_ASSOC);
    $row_id = $check['id'];
    // do something
}

Wenn Sie mehrere Zeilen erwarten, entfernen Sie die LIMIT 1und ändern Sie die Abrufmethode in fetchAll:

$q = $db->prepare("SELECT id FROM table WHERE forename = :forename and surname = :surname");// removed limit 1
$q->bindValue(':forename', 'Joe');
$q->bindValue(':surname',  'Bloggs');
$q->execute();

if ($q->rowCount() > 0){
    $check = $q->fetchAll(PDO::FETCH_ASSOC);
    //$check will now hold an array of returned rows. 
    //let's say we need the second result, i.e. index of 1
    $row_id = $check[1]['id']; 
    // do something
}
Gilly
quelle
Nicht sicher. Scheint mir eine gültige Antwort zu sein. Ich denke, es würde von der Verwendung von 'myname' anstelle von 'name' und der Verwendung mehrerer Parameter anstelle von nur einem profitieren.
Joe Phillips
@ GillianLoWong Was macht das $check = $q->fetch(PDO::FETCH_ASSOC); if (!empty($check)){ $row_id = $check['id']; // do something }?
Abdul
1
Hallo @abdul, ich habe die Anzahl / Leer-Prüfung des Arrays ersetzt. Es sollte sehen, ob irgendwelche Ergebnisse zurückgegeben wurden. Pdo verfügt jedoch auch über eine Funktion namens rowCount (), mit der Sie überprüfen können, ob Zeilen überhaupt betroffen / abgerufen wurden. Es macht keinen Sinn, Daten abzurufen, wenn Sie nicht einmal wissen, ob Zeilen ausgewählt wurden. Deshalb habe ich die Anweisung fetch in die Anweisung if rowCount () verschoben. :)
Gilly
@ Gillian La Wong, vielen Dank für Ihre saubere Abfrage von bindValue für mehrere Abfragen. das rette mein Projekt.
PHP-Codierer
6

Eine kleine, vollständige Antwort finden Sie hier: Alle sind einsatzbereit:

    $sql = "SELECT `username` FROM `users` WHERE `id` = :id";
    $q = $dbh->prepare($sql);
    $q->execute(array(':id' => "4"));
    $done= $q->fetch();

 echo $done[0];

Hier $dbhist der PDO-DB-Konnektor, und basierend auf idder Tabelle haben userswir die usernameVerwendungfetch();

Ich hoffe das hilft jemandem, Viel Spaß!

Domuta Marcel
quelle
Oder verwenden Sie fetchColumn(), um die [0]Notwendigkeit zu vermeiden . Denken Sie auch daran, LIMIT 1in SQL zu verwenden.
Rybo111
3

Methode 1: Verwenden Sie die PDO-Abfragemethode

$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

Zeilenanzahl abrufen

$stmt = $db->query('SELECT id FROM Employee where name ="'.$name.'"');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';

Methode 2: Anweisungen mit Parametern

$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->execute(array($name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Methode 3: Bindungsparameter

$stmt = $db->prepare("SELECT id FROM Employee WHERE name=?");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

**bind with named parameters**
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

or
$stmt = $db->prepare("SELECT id FROM Employee WHERE name=:name");
$stmt->execute(array(':name' => $name));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

Weitere Informationen finden Sie unter diesem Link

Sudhir
quelle
4
Bitte entfernen Sie Methode 1. Es ermöglicht MySQL-Injektion.
Tomahock
-2

Wenn Sie Inline-Codierung auf einer einzelnen Seite verwenden und kein Hoppla verwenden, als dieses vollständige Beispiel zu verwenden, wird dies sicherlich hilfreich sein

//connect to the db
$dbh = new PDO('mysql:host=localhost;dbname=mydb', dbuser, dbpw); 

//build the query
$query="SELECT field1, field2
FROM ubertable
WHERE field1 > 6969";

//execute the query
$data = $dbh->query($query);
//convert result resource to array
$result = $data->fetchAll(PDO::FETCH_ASSOC);

//view the entire array (for testing)
print_r($result);

//display array elements
foreach($result as $output) {
echo output[field1] . " " . output[field1] . "<br />";
}
Shiv Singh
quelle
Dieses Code-Snippet kann das Problem zwar lösen, erklärt jedoch nicht, warum oder wie es die Frage beantwortet. Bitte geben Sie eine Erklärung für Ihren Code an , da dies wirklich zur Verbesserung der Qualität Ihres Beitrags beiträgt. Denken Sie daran, dass Sie die Frage für Leser in Zukunft beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen. Flagger / Rezensenten: Für Nur-Code-Antworten wie diese, Downvote, nicht löschen!
Scott Weldon
Also, was soll ich es selbst löschen
Shiv Singh
Nein, genau das Gegenteil. Ich bin auf diesen Beitrag in der Warteschlange für Beiträge mit geringer Qualität gestoßen , und so bestand der letzte Teil meines Kommentars darin, den Leuten zu sagen, dass sie nicht abstimmen sollen, um ihn zu löschen. (Der Vorschlag, stattdessen abzustimmen, sollte zu vorläufigen Abstimmungen führen, die entfernt werden, nachdem Ihr Beitrag bearbeitet wurde.) Wie in meinem vorherigen Kommentar erwähnt, ist es besser, wenn Sie eine Erklärung hinzufügen, warum Sie den von Ihnen verwendeten Code vorgeschlagen haben . Diese Frage fragt auch nach parametrisierten Abfragen, field > 6969sieht jedoch eher fest codiert als parametrisiert aus.
Scott Weldon