Come posso utilizzare correttamente un oggetto PDO per una query SELECT con parametri


85

Ho provato a seguire le istruzioni di PHP.net per eseguire SELECTquery, ma non sono sicuro del modo migliore per farlo.

Vorrei utilizzare una SELECTquery parametrizzata , se possibile, per restituire il IDin una tabella in cui il namecampo corrisponde al parametro. Questo dovrebbe restituirne uno IDperché sarà unico.

Vorrei quindi usarlo IDper un INSERTin un'altra tabella, quindi dovrò determinare se ha avuto successo o meno.

Ho anche letto che puoi preparare le query per il riutilizzo, ma non ero sicuro di come questo aiutasse.

Risposte:


158

Seleziona i dati in questo modo:

$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

Si inserisce allo stesso modo:

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

Ti consiglio di configurare PDO per generare eccezioni in caso di errore. Si riceverà quindi un messaggio PDOExceptiondi errore se una qualsiasi delle query ha esito negativo: non è necessario controllare esplicitamente. Per attivare le eccezioni, chiamalo subito dopo aver creato l' $dboggetto:

$db = new PDO("...");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Presumo tu intenda PDOStatement in cui hai un nuovo PDO (...), giusto?
Joe Phillips

1
no. PDO è la classe di connessione (probabilmente avrebbe dovuto essere chiamata PdoConnection). La connessione può creare PdoStatements. Chiami setAttribute () sull'oggetto connessione, non sulle singole istruzioni. (In alternativa, puoi passarlo al costruttore)
troelskn

1
questo potrebbe essere utile:$db = new PDO('mysql:dbname=your_database;host=localhost', 'junior', '444');
Junior Mayhé

2
Per la linea $statement->execute(array(':name' => "Jimbo"));, puoi spiegare la parte di Jimbo?
muttley91

1
@rar Nella riga precedente, la query viene avviata con un segnaposto :name. La chiamata executequi viene eseguita con un array associativo di segnaposto -> coppie di valori. Quindi in questo caso, il :namesegnaposto verrà sostituito con la stringa Jimbo. Si noti che non si tratta semplicemente di sostituire una stringa, poiché il valore viene sottoposto a escape o inviato su un canale diverso dalla query effettiva, prevenendo così qualsiasi tipo di attacco di iniezione.
troelskn

16

Ultimamente ho lavorato con PDO e la risposta sopra è completamente corretta, ma volevo solo documentare che anche quanto segue funziona.

$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();

16
No, non è così, poiché non hai selezionato quale database utilizzare.
Rápli András

3
Dovrebbe essere effettivamente nella stringa "server", che in realtà dovrebbe essere un DSN nella forma di "{driver}: dbname = {db_name}; host = {server}" sostituendo i valori delle parentesi graffe con qualunque cosa la tua connessione abbia bisogno
thorne51

12

Puoi utilizzare i metodi bindParamo bindValueper preparare la tua dichiarazione. Rende le cose più chiare a prima vista invece di farlo$check->execute(array(':name' => $name)); Soprattutto se si legano più valori / variabili.

Controlla l'esempio chiaro e di facile lettura di seguito:

$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
}

Se ti aspetti più righe, rimuovi LIMIT 1e modifica il metodo di recupero 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
}

Non sono sicuro. Mi sembra una valida risposta. Penso che trarrebbe vantaggio dall'uso di "myname" invece di "name" e anche dall'utilizzo di più parametri invece di uno solo.
Joe Phillips

@GillianLoWong Cosa fa $check = $q->fetch(PDO::FETCH_ASSOC); if (!empty($check)){ $row_id = $check['id']; // do something }?
Abdul

1
Ciao @abdul, ho sostituito il controllo di conteggio / vuoto sull'array. Doveva vedere se i risultati venivano restituiti. Ma pdo ha anche una funzione chiamata rowCount () che ti consente di controllare se qualche riga è stata interessata / recuperata. Non ha senso recuperare i dati se non si sa nemmeno se sono state selezionate righe, quindi ho spostato l'istruzione fetch nell'istruzione if rowCount (). :)
Gilly

@Gillian La Wong grazie per la tua query pulita di bindValue per più query where. che salva il mio progetto.
php-coder

6

Una risposta un po 'completa è qui con tutto pronto per l'uso:

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

 echo $done[0];

Ecco il $dbhconnettore db PDO e basato sulla idtabellausers abbiamo ottenuto ilusername utilizzofetch();

Spero che questo aiuti qualcuno, divertiti!


Oppure usa fetchColumn()per evitare di [0]essere necessario. Inoltre, ricorda di usare LIMIT 1nell'SQL.
rybo111

3

Metodo 1: USA il metodo di query PDO

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

Ottenere il conteggio delle righe

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

Metodo 2: dichiarazioni con parametri

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

Metodo 3: associa i parametri

$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);

Vuoi saperne di più guarda questo link


4
Rimuovere il metodo 1. Consente l'iniezione di mysql.
Tomahock

-2

se stai usando la codifica in linea in una singola pagina e non usi oops rispetto a questo esempio completo, sarà sicuramente d'aiuto

//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 />";
}

Sebbene questo frammento di codice possa risolvere il problema, non spiega perché o come risponde alla domanda. Per favore includi una spiegazione per il tuo codice , in quanto aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e quelle persone potrebbero non conoscere i motivi del tuo suggerimento sul codice. Segnalatori / revisori: per risposte di solo codice come questa,
Scott Weldon

Quindi cosa dovrei cancellarlo da solo
Shiv Singh

No, esattamente l'opposto. Mi sono imbattuto in questo post nella coda dei post di bassa qualità , quindi l'ultima parte del mio commento era per dire alle persone di non votare per l'eliminazione. (Il suggerimento di downvote invece aveva lo scopo di richiedere downvotes provvisori, che sarebbero stati rimossi dopo che il tuo post è stato modificato.) Come accennato nel mio commento precedente, sarebbe meglio se avessi aggiunto una spiegazione del motivo per cui hai suggerito il codice che hai fatto . Inoltre, questa domanda fa riferimento a query parametrizzate, ma field > 6969sembra hardcoded piuttosto che parametrizzata.
Scott Weldon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.