vorige Präsentation: PHP und Datenbank | zurück zum Buch-Kapitel [esc] | Nächste Präsentation Struktur einer Web-Applikation
In folgenden PHP-Beispielen wird eine Datenbank mit den Tabellen users und projects verwendet.
So kann mein ein einfaches SELECT von PHP aus absetzten. Als Antwort erhält man von der Datenbank eine ganze Tabelle an Werten: mehrere Zeilen (hier: Personen) mit mehreren Spalten (hier: die verscheidenen Eigenschaften der Person)
$sth =$dbh->query(
"SELECT * FROM users WHERE profile_visible ORDER BY surname LIMIT 500"
);
$users = $sth->fetchAll();
Die SQL-Anfrage wird hier als String an die query()-Methode des Datenbankhandler
übergeben.
Der Rückgabewert von query ist ein Statement-Handle $sth (ähnlich
dem Datenbank-Handle).
Erst beim Aufruf von fetchAll() werden die Daten von der
Datenbank geladen.
$sth =$dbh->query(
"SELECT * FROM users WHERE profile_visible ORDER BY surname LIMIT 500"
);
$users = $sth->fetchAll();
echo "Der erste User heisst $users[0][2]"
$users enthält nun ein Array aller Datensätze, jeder
Datensatz ist wieder ein Array.
Mit dem Befehl print_r kann man die gesamte Datenstruktur auf einmal ausgeben - das ist nur fürs debuggen geeignet, nicht für Enduser:
<pre><?php print_r($users) ?></pre>

Jeder Datensatz enthält also die Werte zweimal: einmal unter einem numerischen index 0,1,2… und einmal unter dem Namen der Datenbank-Spalte.
Mit der foreach Schleife kann man ein Array abarbeiten. Nach dem Schlüsselwort as gibt man die Schleifenvariable an, die bei jedem Durchlauf auf eine anderen Eintrag des Arrays gesetzt wird.
foreach( $users as $user ) {
// gib Vorname und Nachname aus
echo "<h2>$user[1] $user[2]</h2>";
}
Falls man den Index auch anzeigen will, kann man die ausführlichere Version
der foreach Schleife verwenden:
foreach($personen as $i => $person) {
echo "<li>Person Nr. $i) $person->firstname $person->surname</li>\n";
}
Achtung: $i ist hier der Index im Array das fetchAll() erzeugt
hat, es ist nicht der Primary Key aus der Datenbank! Den würde man
mit $person->id erhalten!
Bei der “Übersetzung” von Datensätzen zu PHP Datenstrukturen gibt es mehrere Möglichkeiten. Wir können direkt bei fetchAll eine Option angeben.
$sth =$dbh->query(
"SELECT * FROM users WHERE profile_visible ORDER BY lastname LIMIT 500"
);
$users = $sth->fetchAll(PDO::FETCH_NUM);
echo "Der erste User heisst $users[0][2]"
Mit der Option PDO::FETCH_ASSOC erhalten wir die Datensätze als Array, aber der Index ist kein Integer, sondern ein String: jeweils der Name der Tabellen-Spalten entsprechen.
Der Zugriff erfolgt mit eckigen Klammern, wie bei jedem Array: $users[0]['firstname'];
Bei der Verwendung innerhalb eines Strings gibt es aber Probleme: "Der Vorname ist $users[0]['firstname']" funktioniert nicht. Hier braucht man extra geschwungene Klammern rund um die Variable im String.
$sth =$dbh->query(
"SELECT * FROM users WHERE profile_visible ORDER BY lastname LIMIT 500"
);
$users = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach( $users as $user ) {
echo "<h2>{$user['firstname']} {$user['lastname']}</h2>";
}
Mit der Option PDO::FETCH_OBJ erhalten wir die Datensätze als Objekte.
Die Objekte gehören zur Klasse stdClass, haben keine Methoden und haben genau die Eigenschaften die den Tabellen-Spalten entsprechen.
$sth =$dbh->query(
"SELECT * FROM users WHERE profile_visible ORDER BY lastname LIMIT 500"
);
$users = $sth->fetchAll(PDO::FETCH_OBJ);
foreach( $users as $user ) {
echo "<h2>$user->firstname $user->lastname</h2>";
}
Wenn man sich für einen Modus entschieden hat, kann man diesen gleich beim Verbindungsaufbau festlegen:
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
Mit der SQL-Funktion COUNT() können
wir die Anzahl der gefundenen Datensätze bestimmen*. Wir wollen also nur einen einzigen Wert aus der Datenbank laden.
Trotzdem brauchen wir mehrere Schritte:
$sth = $dbh->query("SELECT COUNT(*) AS anzahl FROM users WHERE profile_visible");
$result = $sth->fetchAll(PDO::FETCH_OBJ);
$anz_personen = $result[0]->anzahl;
Hier wurde in SQL mit AS eine neue “Spalte” namens anzahl erzeugt. Diese ist dann in PHP auch unter diesem Namen zugänglich.
Man könnte all diese Befehle direkt aneinander-ketten (englisch: “to chain”):
$anz_personen = $dbh->query("SELECT COUNT(*) AS anzahl FROM users WHERE profile_visible")->fetchAll(PDO::FETCH_OBJ)[0]->anzahl;
Damit spart man sich Variablen, macht aber die Fehlersuche etwas schwieriger.
Das Laden der Datensätze aus der Datenbank braucht Zeit. Wenn es Millionen von Datensätzen sind kann das zum Problem werden. In dieser SQL Abfrage wird damit schon gut umgegangen:
$sth =$dbh->query(
"SELECT * FROM person WHERE profile_visible=1 ORDER BY surname LIMIT 500"
);
$personen = $sth->fetchAll();
Im Beispiel wird LIMIT verwendet:
LIMIT anzahl bzw.
LIMIT anzahl OFFSET anfangsposition
wählt aus der Antwort eine Anzahl von Datensätzen aus, beginnt dabei bei
Anfangsposition*.
In der Datenbank sind Personen, deren Profil nicht angezeigt werden soll, mit
profile_visible = false gekennzeichnet. Im SQL-Statement wird sicher gestellt, dass
nur sichtbare Profil angezeigt werden.
Wie kann man zufällige Datensätze auswählen?
$query =$dbh->query(
"SELECT * FROM users
TABLESAMPLE BERNOULLI (1)
WHERE profile_visible
ORDER BY lastname
LIMIT 10;"
);
$personen = $query->fetchAll(PDO::FETCH_OBJ);
Für sehr kleine Tabellen funktioniert diese Methode besser:
$query =$dbh->query(
"SELECT * FROM users
ORDER BY RANDOM()
LIMIT 3;"
);
$personen = $query->fetchAll(PDO::FETCH_OBJ);
PHP
Postgres
vorige Präsentation: PHP und Datenbank | zurück zum Buch-Kapitel [esc] | Nächste Präsentation Struktur einer Web-Applikation
/
#