PHP und PDO: die erste Ausgabe
Lösung geprüft
Die Aufgabe der heutigen Stunde ist die erste PHP-Seite mit Datenbankzugriff! Bis jetzt haben wir SQL immer direkt in phpMyAdmin eingetippt. Jetzt holt ein Programm die Daten und gibt sie als Webseite aus – und genau dafür gibt es PDO.
Aufgabe 1: PHP und PDO. Eine einfache Ausgabe mit PDO in PHP. PHP-Datei hier einfügen.
Die Testdatenbank „schule"
Alle PHP-Aufgaben laufen auf derselben Datenbank:
Schüler(id, nachname, vorname, geburtsdatum, strassenr, plz, ort)
Kurs(id, f_id, art, stufe, wochenstunden)
Fach(id, fach)
belegt(s_id, k_id, punkte)
leitet(s_id, ng_id, stunden)
Nachhilfegruppe(id, f_id)
erDiagram
Fach ||--o{ Kurs : "f_id"
Fach ||--o{ Nachhilfegruppe : "f_id"
"Schüler" ||--o{ belegt : "s_id"
Kurs ||--o{ belegt : "k_id"
"Schüler" ||--o{ leitet : "s_id"
Nachhilfegruppe ||--o{ leitet : "ng_id"
"Schüler" {
int id PK
string nachname
string vorname
date geburtsdatum
string strassenr
int plz
string ort
}
Fach {
int id PK
string fach
}
Kurs {
int id PK
int f_id FK
string art
string stufe
int wochenstunden
}
belegt {
int s_id FK
int k_id FK
int punkte
}
Nachhilfegruppe {
int id PK
int f_id FK
}
leitet {
int s_id FK
int ng_id FK
int stunden
}
Warum PDO und nicht etwas anderes
In PHP gibt es drei Wege, auf eine MySQL-Datenbank zuzugreifen:
| Weg | Stand |
|---|---|
mysql_* | veraltet, in PHP 7 komplett entfernt – gar nicht erst anfangen |
| MySQLi | funktioniert, aber nur für MySQL |
| PDO | das aktuellste Interface, funktioniert auch mit anderen Datenbanksystemen |
Wenn du im Netz ein Tutorial findest, in dem mysql_query(...)
steht: zuklappen und ein anderes suchen. Das ist mindestens zehn Jahre
alt und läuft auf keinem aktuellen Server mehr.
sequenceDiagram
participant B as Browser
participant P as ausgabe.php
participant D as PDO
participant M as MySQL
B->>P: Aufruf von ausgabe.php
P->>D: new PDO(...schule)
D->>M: verbinden,<br>SET NAMES utf8
M-->>D: Verbindung steht
P->>D: query("SELECT *<br>FROM schüler")
D->>M: SQL absetzen
M-->>D: Ergebniszeilen
D-->>P: Ergebnis zum<br>Durchlaufen
P->>P: foreach:<br>$row['vorname'],<br>$row['nachname']
P-->>B: fertiges HTML
Lösungsprozess der Aufgabe
<?php
/**
*
* Eine einfache Ausgabe mit PDO
*
* @version 1.0 vom 16.05.2019
* @meininfokurs.cmrg.site
*/
// Verbindung zur Datenbank aufbauen
$pdo = new PDO('mysql:host=localhost;dbname=schule', 'root', '',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
$sql = "SELECT * FROM schüler";
// Variante 1: direkt ueber query() und foreach
foreach ($pdo->query($sql) as $row) {
echo $row['vorname']." ".$row['nachname']."<br />";
}
// Variante 2: ueber prepare() und execute()
$sth = $pdo->prepare("SELECT * FROM schüler");
$sth->execute();
echo '<br/>';
/* Alle Datensätze ausgeben */
print("Alle Datensätze ausgeben:");
echo '<br/>';
$result = $sth->fetchAll();
print_r($result);
?>
Die Verbindungszeile
$pdo = new PDO('mysql:host=localhost;dbname=schule', 'root', '',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
| Teil | Bedeutung |
|---|---|
mysql:host=localhost | Datenbanktyp und Server – bei XAMPP läuft beides auf dem eigenen Rechner |
dbname=schule | welche Datenbank |
'root' | Benutzername |
'' | Passwort – bei XAMPP standardmäßig leer |
SET NAMES utf8 | Zeichensatz, damit Umlaute nicht als Fragezeichen erscheinen |
Das utf8 ist kein Luxus. Ohne das steht in der Ausgabe
„Müller" statt „Müller" und der Tabellenname schüler
funktioniert auch nicht. Das ist der Fehler, den bei dieser Aufgabe fast
jeder einmal hat.
root ohne Passwort ist nur in Ordnung, weil
das alles lokal in XAMPP auf dem eigenen Rechner läuft. Auf einem echten
Server legt man einen eigenen Benutzer an, der nur auf diese eine
Datenbank darf – und gibt ihm ein Passwort.
query() und foreach
foreach ($pdo->query($sql) as $row) {
echo $row['vorname']." ".$row['nachname']."<br />";
}
query() schickt das SQL an die Datenbank und gibt etwas
zurück, das man mit foreach durchlaufen kann – genau wie eine
ArrayList in Java. Jeder Durchlauf liefert eine Zeile in
$row.
$row['vorname'] greift über den Spaltennamen
zu. So ein Array nennt man assoziativ: der Index ist kein
Zähler, sondern ein Text. In Aufgabe 5 kommt die Variante ohne das noch
dran.
Der Punkt . ist in PHP das, was in Java das Plus ist: er
hängt Texte aneinander. Wer aus Java kommt, schreibt hier reflexhaft ein
+ – das ergibt in PHP aber eine Addition und damit meistens
eine 0.
prepare() und execute()
$sth = $pdo->prepare("SELECT * FROM schüler");
$sth->execute();
$result = $sth->fetchAll();
Der zweite Weg macht dasselbe in zwei Schritten: erst die Anfrage vorbereiten, dann ausführen. Das sieht umständlicher aus und ist es hier auch – sobald aber Benutzereingaben in die Abfrage kommen, ist dieser Weg der einzig richtige. Warum, kommt beim Thema SQL-Injection.
fetchAll() holt alle Zeilen auf einmal in ein Array, und
print_r() gibt dieses Array mit allen Schlüsseln aus. Das ist
kein hübscher Output für eine Webseite, aber unschlagbar zum Nachschauen,
wie die Daten überhaupt aussehen.
Die Ausgabe
Müller Peter
Gamler Kevin
Ritter Jörg
Ritter Miriam
Rose Stefanie
Sproß Marie
Klasen Daniel
Margel Lukas
Alle Datensätze ausgeben:
Array ( [0] => Array ( [id] => 1 [0] => 1 [nachname] => Peter [1] => Peter ... ) ... )
Beim print_r fällt etwas auf: jeder Wert steht
zweimal drin – einmal unter dem Spaltennamen und einmal
unter einer Nummer. PDO liefert standardmäßig beides. Genau darauf baut
Aufgabe 5 auf, die nur mit den Nummern arbeitet.
Übrigens: <br /> im echo ist HTML, kein
PHP. Ein \n würde im Quelltext einen Zeilenumbruch machen,
im Browser aber nichts – dort muss ein <br> stehen.