Lavorare con il database in Drupal 7 – Lezione 12 – Condizioni delle query (WHERE, HAVING, LIKE)
Una condizione di query consente di selezionare solo i record che soddisfano determinati criteri, ad esempio i nodi creati non più di due settimane fa, o i termini che contengono la parola "drupal", e così via. In SQL utilizziamo WHERE e HAVING per impostare le condizioni nei comandi SELECT, UPDATE e DELETE. Anche nelle query dinamiche di Drupal è implementato un meccanismo per lavorare con le condizioni di query. Questo meccanismo funziona allo stesso modo per tutti e tre i tipi di query: selezione, aggiornamento ed eliminazione.
Concetto delle espressioni condizionali
Una condizione è contenuta in un’espressione speciale che definisce la restrizione della query.
Combinazione (somma, congiunzione)
Ogni condizione può consistere in più espressioni condizionali che vengono combinate insieme. Le condizioni si combinano utilizzando gli operatori AND (E) e OR (O).
Oggetto condizione
Drupal rappresenta ogni frammento di condizione come un’istanza della classe QueryConditional. L’oggetto condizione è quindi un’istanza di questa classe.
Vediamo un esempio di query SQL:
Query:
SELECT FROM {mytable} WHERE (a = 1 AND b = 'foo' OR (c = 'bar'))
Espressione condizionale:
WHERE (a = 1 AND b = 'foo' OR (c = 'bar'))
Parti dell’espressione condizionale:
(a = 1 AND b = 'foo' OR (c = 'bar'))
(c = 'bar')
Operatori di combinazione delle condizioni:
AND, OR
Gli oggetti di query SELECT, UPDATE e DELETE vengono implementati tramite la classe QueryConditionalInterface, che fornisce le interfacce per ciascuno dei tre tipi di query. Successivamente, questo oggetto viene racchiuso in un oggetto QueryConditional. La classe QueryConditional può anche essere invocata direttamente.
Ogni frammento di espressione condizionale viene unito tramite l’operatore AND. Uno o più frammenti possono essere combinati con altri operatori, come OR.
API
Ci sono due metodi principali per lavorare con gli oggetti condizionali:
$query->condition($field, $value = NULL, $operator = '=')
Il metodo condition() consente di definire il campo, il valore e l’operatore di una condizione nella query. Questo metodo può essere utilizzato per definire condizioni con confronti binari (vero o falso), come =
, <
, >=
, LIKE
e così via. Se l’operatore non è specificato, viene utilizzato =
come impostazione predefinita (cioè la corrispondenza esatta). Quindi, per un confronto semplice, possiamo scrivere condition('myfield', $value)
, che verrà convertito in myfield = :value
, dove :value
sarà sostituito con il valore della variabile $value
.
$query->where($snippet, $args = array())
Il metodo where() è un metodo aggiuntivo: possiamo utilizzare condition()
al suo posto, ma where()
viene spesso usato, quindi è stato creato un metodo separato. Nella variabile $snippet
scriviamo la parte SQL pura, mentre in $args
passiamo un array di sostituzioni per i segnaposto della query.
L’uso di condition() è preferibile rispetto a where().
Condizioni con array
A volte è necessario creare una condizione che contenga più valori. In questo caso, possiamo passare un array di valori alla query. Gli operatori SQL più comuni in questi casi sono IN e BETWEEN. L’operatore IN restituisce solo i record che corrispondono esattamente a uno degli elementi dell’array.
<?php $query->condition('myfield', array(1, 2, 3), 'IN'); // Diventa: myfield IN (:db_placeholder_1, :db_placeholder_2, :db_placeholder_3) ?>
In questo modo, selezioneremo tutti i record in cui il campo myfield ha i valori 1, 2 o 3.
Se invece vogliamo specificare un intervallo di valori, possiamo usare BETWEEN:
<?php $query->condition('myfield', array(5, 10), 'BETWEEN'); // Diventa: myfield BETWEEN :db_placeholder_1 AND :db_placeholder_2 ?>
Così selezioniamo tutti i record in cui il campo myfield ha valori compresi tra 5 e 10.
Condizioni nidificate
Il primo parametro di condition() può accettare anche un altro oggetto condizione. Una query nidificata può quindi essere inclusa in una query più complessa. In questo modo possiamo ottenere condizioni composte combinate con operatori AND e OR dove necessario.
Il helper db_condition() restituisce un nuovo oggetto condizione. Questo metodo accetta un parametro, che specifica il tipo di combinazione da utilizzare. È anche possibile usare gli helper db_or(), db_xor() (esclusivo OR), db_and(); questi sono generalmente sufficienti per la maggior parte dei casi. Vediamo un esempio:
<?php $query ->condition('field1', array(1, 2), 'IN') ->condition(db_or()->condition('field2', 5)->condition('field3', 6)) // Risultato: // (field1 IN (:db_placeholder_1, :db_placeholder_2) AND (field2 = :db_placeholder_3 OR field3 = :db_placeholder_4)) ?>
Valori NULL
Per verificare i valori NULL utilizza i seguenti metodi:
<?php $query->isNull('myfield'); // Risultato: (myfield IS NULL) $query->isNotNull('myfield'); // Risultato: (myfield IS NOT NULL) ?>
Questi metodi isNull() e isNotNull() possono essere combinati con where() e condition().
Nota: l’uso di condition('myfield', NULL) è deprecato; usa invece isNull() o isNotNull().
Sottoquery
Il metodo condition() supporta anche le sottoquery come valore di $value
. Per usare una sottoquery si utilizza la classe SelectQuery, creata tramite il metodo db_select(). Invece di eseguire direttamente select(), all’oggetto vengono passati i parametri del metodo condition().
Le sottoquery sono utili per query brevi e semplici con una condizione su un singolo campo. Se stai cercando di costruire qualcosa di molto complesso con db_select(), è meglio fermarsi e usare condition().
Vediamo alcuni esempi di sottoquery per maggiore chiarezza:
db_delete()
<?php db_delete('sessions') ->condition('timestamp', REQUEST_TIME - $lifetime, '<') ->execute(); // DELETE FROM {sessions} WHERE (timestamp < 1228713473) ?>
db_update()
<?php db_update('sessions') ->fields(array( 'sid' => session_id() )) ->condition('sid', $old_session_id) ->execute(); // UPDATE {sessions} SET sid = 'abcde' WHERE (sid = 'fghij'); ?>
db_delete()
<?php // Da taxonomy_term_save(): $or = db_or()->condition('tid1', 5)->condition('tid2', 6); db_delete('term_relation')->condition($or)->execute(); // DELETE FROM {term_relation} WHERE ((tid1 = 5 OR tid2 = 6)) ?>