Ausgabe ohne assoziierte Arrays
Lösung geprüft
Die Aufgabe der heutigen Stunde ist die Ausgabe ohne assoziierte Arrays!
Bis jetzt haben wir immer $row['vorname'] geschrieben – also
den Spaltennamen. Jetzt soll das Programm für jede beliebige
Tabelle funktionieren, ohne die Spaltennamen zu kennen.
Oftmals sollen Programme für alle Datenbanken funktionieren. In dieser Aufgabe schreiben Sie ein Programm, das ohne die Attributnamen zu benutzen, alle Attribute aller Schüler mithilfe einer for-Schleife ausgibt.
Die for-Schleife wird wie in Java geschrieben, nur dass Variablen mit
einem $ anfangen. Die Methode count(Array) hat
einen Array als Eingabe und gibt die Anzahl der Elemente in einem Array
zurück.
Das Programm soll mit einer for-Schleife (ohne assoziierte Arrays) die Attribute aller Schüler ausgeben. Fertige PHP-Datei hier einfügen.
Warum das überhaupt geht
Erinner dich an die print_r-Ausgabe aus Aufgabe 1. Jeder
Wert stand dort zweimal drin:
Array (
[id] => 1
[0] => 1
[nachname] => Peter
[1] => Peter
[vorname] => Müller
[2] => Müller
...
)
PDO liefert standardmäßig beides: den Zugriff über den Spaltennamen (assoziativ) und über eine Nummer (numerisch). Genau die Nummern benutzen wir jetzt – denn die gibt es in jeder Tabelle, egal wie die Spalten heißen.
Lösungsprozess der Aufgabe
<?php
/**
*
* Ausgabe aller Attribute ueber Indizes und count()
* Funktioniert fuer jede Tabelle, ohne die Spaltennamen zu kennen
*
* @version 1.0 vom 27.05.2019
* @meininfokurs.cmrg.site
*/
$pdo = new PDO('mysql:host=localhost;dbname=schule', 'root', '',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$sth = $pdo->prepare("SELECT * FROM schüler");
$sth->execute();
// PDO::FETCH_NUM liefert nur die nummerierten Indizes, keine Spaltennamen
$ergebnis = $sth->fetchAll(PDO::FETCH_NUM);
echo "<table border='1'>";
// aeussere Schleife: ueber alle Schueler
for ($zeile = 0; $zeile < count($ergebnis); $zeile++) {
echo "<tr>";
// innere Schleife: ueber alle Attribute eines Schuelers
for ($spalte = 0; $spalte < count($ergebnis[$zeile]); $spalte++) {
echo "<td>".$ergebnis[$zeile][$spalte]."</td>";
}
echo "</tr>";
}
echo "</table>";
?>
Zwei verschachtelte Schleifen
Das Ergebnis ist ein zweidimensionales Array – genau wie das Spielfeld bei Schiffe versenken. Der erste Index ist die Zeile, der zweite die Spalte:
$ergebnis[0][2] // dritter Wert des ersten Schuelers
$ergebnis[3][0] // erster Wert des vierten Schuelers
Deshalb braucht man zwei Schleifen: die äußere geht über die Schüler, die innere über deren Attribute. Wie beim Anzeigen des Spielfelds.
count() zweimal – und zwar unterschiedlich
| Aufruf | Liefert | Bei der schule-Datenbank |
|---|---|---|
count($ergebnis) | Anzahl der Zeilen | 8 Schüler |
count($ergebnis[$zeile]) | Anzahl der Spalten in dieser Zeile | 7 Attribute |
Das ist derselbe Unterschied wie feld.length gegen
feld[zeile].length bei zweidimensionalen Arrays in Java. Und
genau darin liegt der Trick der Aufgabe: nirgendwo steht eine 7
oder eine 8 im Code. Das Programm fragt die Größen selbst ab und
funktioniert deshalb auch mit einer Tabelle, die zwölf Spalten hat.
FETCH_NUM
$ergebnis = $sth->fetchAll(PDO::FETCH_NUM);
Ohne den Zusatz liefert fetchAll() beide Zugriffsarten – und
dann zählt count() doppelt. Aus 7 Attributen
würden 14, und die Hälfte der Tabellenzellen wäre eine Wiederholung.
Das ist der Fehler, den bei dieser Aufgabe fast jeder einmal hat. Man sieht ihn sofort an der Ausgabe: jeder Wert steht zweimal nebeneinander.
| Modus | Was im Array steht |
|---|---|
PDO::FETCH_BOTH (Standard) | Spaltennamen und Nummern – count() zählt doppelt |
PDO::FETCH_NUM | nur Nummern – das brauchen wir hier |
PDO::FETCH_ASSOC | nur Spaltennamen – für Aufgabe 1 und 2 |
Die for-Schleife in PHP
for ($i = 0; $i < count($array); $i++) { } // PHP
for (int i = 0; i < array.length; i++) { } // Java
Fast identisch. Die drei Unterschiede: Variablen fangen mit
$ an, es gibt keine Typangabe wie int, und die
Länge holt man mit count(...) statt mit
.length.
Die Ausgabe
+---+----------+--------+------------+---------------------+-------+-----------+
| 1 | Peter | Müller | 1996-04-09 | Ludwigstraße 13 | 64625 | Bensheim |
| 2 | Kevin | Gamler | 1998-02-06 | Nestweg 42 | 64625 | Einhausen |
| 3 | Jörg | Ritter | 1997-11-03 | Laplacestraße 12 | 64625 | Alsbach |
| 4 | Miriam | Ritter | 1997-11-25 | Laplacestrasse 12 | 64625 | Alsbach |
| 5 | Stefanie | Rose | 1997-10-11 | Darmstädterstaße 23 | 64625 | Bensheim |
| 6 | Marie | Sproß | 2003-10-09 | Darmstädterstaße 23 | 64625 | Bensheim |
| 7 | Daniel | Klasen | 2002-03-10 | Darmstädterstaße 25 | 64625 | Bensheim |
| 8 | Lukas | Margel | 2000-05-13 | Dr. Hesse Weg 14 | 64625 | Bensheim |
+---+----------+--------+------------+---------------------+-------+-----------+
Was jetzt fehlt, ist die Kopfzeile – die Spaltennamen kennen wir ja
absichtlich nicht mehr. Will man sie trotzdem, holt man sie über
$sth->getColumnMeta($i)['name'] aus der Datenbank. Damit
bleibt das Programm allgemein und hat trotzdem Überschriften. Gefordert
war das hier nicht.