query
In questo articolo viene trattata la funzione mysqli_query() in PHP, usata per eseguire istruzioni SQL su un database MySQL.
$mysqli->query() esegue una singola istruzione SQL su un database MySQL tramite una connessione MySQLi aperta. È il modo più semplice per comunicare con MySQL da PHP ed è quindi il punto di partenza ideale — ma, come vedrai qui sotto, nel momento in cui la query contiene input dell'utente dovresti ricorrere alle prepared statement.
Questa pagina illustra cosa restituisce query(), come leggere un result set, come si comporta per le query di scrittura e la trappola dell'SQL injection che devi assolutamente evitare.
Sintassi
// Object-oriented style
$result = $mysqli->query($sql);
// Procedural style
$result = mysqli_query($mysqli, $sql);Entrambe le forme fanno la stessa cosa; lo stile OOP viene usato in tutta questa pagina.
Cosa restituisce query()
Il valore restituito dipende dal tipo di istruzione eseguita:
| Tipo di query | In caso di successo | In caso di errore |
|---|---|---|
SELECT, SHOW, DESCRIBE, EXPLAIN | un oggetto mysqli_result | false |
INSERT, UPDATE, DELETE, CREATE, ... | true | false |
Poiché il fallimento restituisce sempre false, puoi ramificare il codice in base al valore restituito con un semplice if. Non dare mai per scontato che una query sia andata a buon fine — un nome di colonna errato o una tabella mancante restituiscono entrambi false.
Eseguire una query SELECT
Per una SELECT, scorri il result set restituito e preleva ogni riga con fetch_assoc() (oppure fetch_array()), poi libera il result set quando hai finito:
<?php
$mysqli = new mysqli("localhost", "username", "password", "database");
// Stop early if the connection failed.
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: " . $mysqli->connect_error;
exit();
}
$result = $mysqli->query("SELECT id, name FROM users");
if ($result) {
while ($row = $result->fetch_assoc()) {
echo $row["id"] . ": " . $row["name"] . "\n";
}
$result->free(); // release the result set's memory
} else {
echo "Query failed: " . $mysqli->error;
}
$mysqli->close();
?>Il ciclo while termina quando fetch_assoc() restituisce null (nessuna altra riga). $result->free() libera la memoria del result set, aspetto importante negli script a lunga esecuzione che effettuano molte query.
Eseguire INSERT, UPDATE e DELETE
Le query di scrittura non restituiscono un result set — restituiscono true in caso di successo. Per sapere quante righe sono state interessate, leggi $mysqli->affected_rows; per ottenere l'id auto-increment di una riga appena inserita, leggi $mysqli->insert_id:
<?php
$mysqli = new mysqli("localhost", "username", "password", "database");
if ($mysqli->query("UPDATE users SET active = 1 WHERE active = 0")) {
echo $mysqli->affected_rows . " rows updated";
} else {
echo "Query failed: " . $mysqli->error;
}
$mysqli->close();
?>Non inserire mai direttamente l'input dell'utente in una query
query() riceve una stringa SQL grezza, quindi concatenare l'input dell'utente al suo interno apre la porta all'SQL injection — la falla di sicurezza nei database più comune sul web:
// DANGEROUS — do NOT do this
$id = $_GET['id'];
$result = $mysqli->query("SELECT * FROM users WHERE id = $id");Se un visitatore invia id=0 OR 1=1, quella query restituisce tutti gli utenti. La soluzione è una prepared statement, che invia l'istruzione SQL e i valori separatamente in modo che i valori non possano mai essere interpretati come SQL:
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $_GET['id']); // "i" = integer
$stmt->execute();
$result = $stmt->get_result();Usa query() solo per SQL fisso senza input dell'utente; usa le prepared statement per tutto ciò che contiene valori provenienti dall'esterno del tuo codice. Consulta MySQL prepared statements per una guida completa.
Riepilogo
$mysqli->query()esegue una singola istruzione SQL su una connessione MySQLi aperta.- Una
SELECTrestituisce un oggettomysqli_resultche si itera confetch_assoc(); le altre istruzioni restituisconotrue; qualsiasi errore restituiscefalse. - Leggi
affected_rowsdopo una scrittura einsert_iddopo unINSERT. - Passa alle prepared statement non appena è coinvolto l'input dell'utente.