Query statiche
Le query SELECT più comuni in Drupal sono query statiche che usano il metodo query() dell’oggetto di connessione al database.
Le query statiche vengono passate al database quasi alla lettera.
Esempio:
$database = \Drupal::database();
$query = $database->query("SELECT id, example FROM {mytable}");
$result = $query->fetchAll();
Solo query SELECT molto semplici dovrebbero usare il metodo static query(). Devi usare una query dinamica se ti servono query più complesse, generazione dinamica delle query o variabilità.
Non usare questa funzione per semplici query INSERT, UPDATE o DELETE. Queste devono essere gestite tramite insert(), update() e delete() rispettivamente. Per query DELETE più complesse su più tabelle vedi Query DELETE complesse.
Argomenti
Il metodo query() dell’oggetto di connessione al database accetta tre argomenti:
- $query: la query da eseguire. Usa i placeholder quando necessario e racchiudi sempre i nomi delle tabelle tra parentesi graffe.
- $args: un array di valori per sostituire i placeholder nella query.
- $options: un array di opzioni per controllare il comportamento della query (opzionale).
Prefisso dei nomi delle tabelle
Nelle query statiche tutti i nomi delle tabelle devono essere racchiusi tra parentesi graffe {...}.
Racchiudere i nomi delle tabelle tra parentesi graffe li contrassegna in modo che il sistema del database possa aggiungere un prefisso, se necessario. Il prefisso consente di eseguire più siti con un unico database o, in alcuni casi, di condividere determinate tabelle tra siti. Inoltre è necessario per evitare perdite di dati dal sito host nei test.
Placeholder
I placeholder indicano dove un valore letterale sarà inserito nella query. Separandoli dalla query, permettiamo al database di distinguere tra sintassi SQL e valori forniti dall’utente, prevenendo attacchi di SQL injection.
$query = $database->query("SELECT id, example FROM {mytable} WHERE created > :created", [
':created' => REQUEST_TIME - 3600,
]);
Il codice sopra selezionerà tutti gli ID e gli esempi di mytable creati nell’ultima ora (3600 secondi). Il placeholder :created sarà sostituito dinamicamente dal valore REQUEST_TIME - 3600 al momento dell’esecuzione.
Una query può avere qualsiasi numero di placeholder, ma ciascuno deve avere un nome univoco, anche se hanno lo stesso valore. In base al caso d’uso, l’array dei placeholder può essere definito inline (come sopra) o preparato in anticipo. L’ordine non è importante.
I placeholder che iniziano con db_ sono riservati all’uso interno del sistema e non devono mai essere dichiarati esplicitamente.
I placeholder non devono essere escapati o racchiusi tra virgolette indipendentemente dal loro tipo. Poiché sono inviati separatamente al server del database, quest’ultimo può distinguere da solo tra stringa di query e valore.
// ERRATO (virgolette attorno al placeholder :type)
$result = $database->query("SELECT example FROM {mytable} WHERE type = ':type'", [
':type' => 'mytype',
]);
// CORRETTO (senza virgolette attorno al placeholder :type)
$result = $database->query("SELECT example FROM {mytable} WHERE type = :type", [
':type' => 'mytype',
]);
I placeholder non possono essere usati per nomi di colonne o tabelle. Se provengono da input non sicuri devono essere passati tramite $database->escapeTable().
Array placeholder
Il livello database di Drupal include una funzionalità extra. Se il valore passato a un placeholder è un array, esso verrà automaticamente espanso in un elenco separato da virgole, insieme al placeholder corrispondente. Ciò significa che gli sviluppatori non devono preoccuparsi di contare il numero di placeholder necessari.
Esempio:
$result = $database->query("SELECT * FROM {mytable} WHERE id IN (:ids[])", [':ids[]' => [13, 42, 144]]);
Le seguenti due istruzioni sono equivalenti a quella sopra:
$result = $database->query("SELECT * FROM {mytable} WHERE id IN (:ids_1, :ids_2, :ids_3)", [
':ids_1' => 13,
':ids_2' => 42,
':ids_3' => 144,
]);
$result = $database->query("SELECT * FROM {mytable} WHERE id IN (13, 42, 144)");
Opzioni delle query
Il terzo parametro del metodo query() è un array di opzioni che determinano il comportamento della query. In genere solo due direttive vengono usate dalla maggior parte delle query. Altri valori sono principalmente per uso interno.
La chiave "target" specifica l’obiettivo da usare. Se non viene specificato, il valore predefinito è "default". Attualmente l’unico altro valore valido è "replica", per eseguire la query su un server replica, se disponibile.
La chiave "fetch" indica come recuperare i record restituiti da questa query. I valori validi sono: PDO::FETCH_OBJ, PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH o una stringa che rappresenta il nome di una classe. Se viene specificata una stringa, ogni record sarà recuperato come nuovo oggetto di quella classe. Gli altri valori seguono il comportamento di PDO, restituendo rispettivamente un oggetto stdClass, un array associativo, un array numerico o un array misto. Vedi documentazione PDO. Il valore predefinito è PDO::FETCH_OBJ, che è raccomandato per coerenza salvo necessità diverse.
Esempio: eseguire una query su un server replica, se disponibile, e recuperare i record come array associativo:
$result = $database->query("SELECT id, example FROM {mytable}", [], [
'target' => 'replica',
'fetch' => PDO::FETCH_ASSOC,
]);
L’oggetto risultato restituito da query() può essere usato per ottenere ogni riga e colonna. Ad esempio:
$sql = "SELECT name, quantity FROM goods WHERE vid = :vid";
$result = $database->query($sql, [':vid' => $vid]);
if ($result) {
while ($row = $result->fetchAssoc()) {
// Usa:
// $row['name']
// $row['quantity']
}
}
Query DELETE complesse
Usare una query statica è un modo semplice e compatto per esprimere una query di eliminazione che coinvolge più tabelle in un’unica istruzione.
Esempio:
$database = \Drupal::database();
$database->query("DELETE {table1}, {table2} FROM {table1} INNER JOIN {table2} ON {table1}.id = {table2}.id WHERE {table1}.id=:recno", [":recno" => 2]);
(Elimina la riga sia da table1 che da table2)