Q2 Datenbanken

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.

Die Aufgabenstellung lautet

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

ausgabeFor.php
/* meininfokurs.cmrg.site */
<?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

AufrufLiefertBei der schule-Datenbank
count($ergebnis)Anzahl der Zeilen8 Schüler
count($ergebnis[$zeile])Anzahl der Spalten in dieser Zeile7 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.

ModusWas im Array steht
PDO::FETCH_BOTH (Standard)Spaltennamen und Nummern – count() zählt doppelt
PDO::FETCH_NUMnur Nummern – das brauchen wir hier
PDO::FETCH_ASSOCnur 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

Browser
+---+----------+--------+------------+---------------------+-------+-----------+
| 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.

Aufgabe suchen

Tippe los. Strg+K öffnet die Suche von überall.

Zuletzt angesehen

Werbung