Datenbankabfragen in Drupal 7 – Lektion 4 – Dynamische Abfragen (SELECT)
Wir sind wohl zur interessantesten Komponente der Drupal Database API gelangt: den dynamischen Abfragen. Dynamische Abfragen heißen so, weil Drupal die Abfragezeichenkette dynamisch ergänzt. Alle Einfüge-, Update-, Lösch- oder Merge-Abfragen können dynamisch sein. SELECT-Abfragen können dynamisch oder statisch sein. Dennoch sollten dynamische Abfragen auch für SELECT-Anfragen verwendet werden.
Alle dynamischen Abfragen werden als Abfrageobjekt erstellt und bei Bedarf ausgeführt. Wie bei statischen Abfragen wird meist eine prozedurale Wrapper-Funktion verwendet. Alle weiteren Abfrageparameter können dem Abfrageobjekt hinzugefügt werden.
db_select()-Select-Abfragen
Dynamische SELECT-Abfragen beginnen mit der Funktion db_select()
, zum Beispiel:
<?php $query = db_select('node', 'n', $options); ?>
Hierbei ist "node" die Tabelle, auf die wir zugreifen (entspricht dem FROM in SQL). Beachten Sie, dass der Tabellenname nicht in geschweifte Klammern gesetzt wird – der Query-Builder übernimmt das automatisch. Der zweite Parameter ist ein Alias für die Tabelle. Wenn kein Alias angegeben wird, wird der Tabellenname verwendet. Das optionale Array $options
entspricht dem Array $options
bei statischen Abfragen.
Dynamische SELECT-Abfragen können sehr einfach oder sehr komplex sein. Wir lernen die Grundprinzipien kennen, wobei man sehr viel Zeit in deren Vertiefung investieren kann.
Noch ein Beispiel für db_select()
Unten ein relativ einfacher SELECT auf die Benutzertabelle. Später lernen wir komplexere SELECTs mit Joins kennen.
<?php $query = db_select('users', 'u'); $query ->condition('u.uid', 0, '<>') ->fields('u', array('uid', 'name', 'status', 'created', 'access')) ->range(0, 50); $result = $query->execute(); ?>
Dieses Beispiel entspricht der folgenden SQL-Abfrage:
$result = db_query("SELECT uid, name, status, created, access FROM {users} u WHERE uid <> 0 LIMIT 50 OFFSET 0");
Dies ist eine vereinfachte Form der Benutzerverwaltungsseite, die zum Weiterstudium dienen kann.
Joins (Verknüpfungen)
Für das Verbinden mit anderen Tabellen werden die Methoden join()
, innerJoin()
, leftJoin()
oder rightJoin()
verwendet, zum Beispiel:
<?php $table_alias = $query->join('user', 'u', 'n.uid = u.uid AND u.uid = :uid', array(':uid' => 5)); ?>
Im Beispiel wird ein INNER JOIN mit der Tabelle "user" (Alias "u") angelegt mit der Bedingung ON "n.uid = u.uid AND u.uid = :uid", wobei der Platzhalter :uid den Wert 5 erhält. Beachten Sie die Verwendung von Platzhaltern zum Schutz vor SQL-Injektionen. Die Methoden innerJoin()
, leftJoin()
und rightJoin()
entsprechen den jeweiligen Join-Typen.
Der Rückgabewert von join()
ist der Alias der verbundenen Tabelle. Wenn dieser Alias bereits vergeben ist (was selten passiert), weist Drupal einen anderen Alias zu.
Beispiel mit Subquery als Join:
<?php $myselect = db_select('mytable') ->fields('mytable') ->condition('myfield', 'myvalue'); $alias = $query->join($myselect, 'myalias', 'n.nid = myalias.nid'); ?>
Felder (Fields, addField)
Zum Hinzufügen eines Feldes zur SELECT-Abfrage verwenden Sie addField()
:
<?php $title_field = $query->addField('n', 'title', 'my_title'); ?>
Das Beispiel wählt das Feld "title" aus der Tabelle mit Alias "n" und gibt ihm den Alias "my_title". Wenn kein Alias definiert wird, erzeugt Drupal automatisch einen. Bei Konflikten werden alternative Aliase wie "n_title" oder "n_title_2" vergeben.
Um mehrere Felder auf einmal hinzuzufügen, nutzen Sie fields()
:
<?php $query->fields('n', array('nid', 'title', 'created', 'uid')); ?>
Dies entspricht dem mehrfachen Aufruf von addField()
, unterstützt aber keine Aliase. Wird fields()
ohne Feldnamen aufgerufen, entspricht dies einem "SELECT *".
DISTINCT
Um Duplikate im Ergebnis zu entfernen, verwenden Sie distinct()
:
<?php $query->distinct(); ?>
Nutzen Sie DISTINCT jedoch sparsam, da es die Leistung beeinträchtigen kann.
Ausdrücke (Expressions, addExpression)
Zur Verwendung von SQL-Ausdrücken im SELECT nutzen Sie addExpression()
:
<?php $count_alias = $query->addExpression('COUNT(uid)', 'uid_count'); $count_alias = $query->addExpression('created - :offset', 'time_diff', array(':offset' => 3600)); ?>
Der zweite Parameter ist der Alias. Optional kann ein Array von Platzhaltern übergeben werden.
ORDER BY (Sortierung, orderBy)
Fügen Sie eine Sortierung hinzu mit orderBy()
:
<?php $query->orderBy('title', 'DESC'); ?>
Standard ist aufsteigend (ASC). Mehrere Sortierungen sind durch mehrfaches Aufrufen möglich.
Zufällige Reihenfolge (orderRandom)
Verwenden Sie orderRandom()
um Ergebnisse zufällig zu sortieren:
<?php $query->orderRandom(); ?>
Dies kann mit orderBy()
kombiniert werden.
GROUP BY (Gruppierung)
Gruppieren Sie Ergebnisse mit groupBy()
:
<?php $query->groupBy('uid'); ?>
Mehrere Gruppierungen sind durch mehrfaches Aufrufen möglich.
Range und Limits (range)
Begrenzen Sie die Anzahl der zurückgegebenen Zeilen mit range()
:
<?php $query->range(5, 10); ?>
Gibt 10 Datensätze ab dem 6. Datensatz zurück (Nullbasiert). Ein erneutes Aufrufen überschreibt vorherige Werte.
Sortierung von Tabellen (extend)
Zur Unterstützung sortierbarer Tabellen verwenden Sie das Extension-System mit extend('TableSort')
:
<?php $query = $query ->extend('TableSort') ->orderByHeader($header); ?>
Bedingungen (condition)
Bedingungen sind komplex und werden später detailliert behandelt. Für WHERE verwenden Sie condition()
oder where()
, für HAVING havingCondition()
oder having()
.
Ausführen der Abfrage (execute)
Rufen Sie execute()
auf, um die Abfrage auszuführen:
<?php $result = $query->execute(); ?>
Das Ergebnis kann wie gewohnt verarbeitet werden, z.B. mit foreach
:
<?php foreach ($result as $record) { // Verarbeitung von $record } ?>
- fetchField()
- fetchAllKeyed()
- fetchCol()
Diese Methoden erfordern oft definierte Alias-Namen.
Zählen von Ergebnissen
Erstellen Sie eine Zähl-Abfrage mit countQuery()
:
<?php $count_query = $query->countQuery(); $num_rows = $count_query->execute()->fetchField(); ?>
Debugging
Zum Anzeigen der generierten SQL-Abfrage verwenden Sie __toString()
:
<?php print_r($query->__toString()); ?>