Einführung
Diese kleine Programmierübung soll die generellen Zugriffe per PHP / MySQLi Technik darstellen. Hierzu sollen die Befehlsstrukturen mit OOP / MySQLi / Prepared Statements umgesetzt werden. Die hier dargestellten Beispielskripte sind eine Zusammenfassung von PHP-Datenbank-Übungen, wie wir sie im Rahmen unserer "PHP & MySQL"-Seminare für das Zertifikat "CMS Online Designer (VHS)" schulen.
Schwerpunkt liegt auf der Umsetzung mit OOP (Prepared Statments) - daher hier eine kurze Darstellung / Erinnerung
Prozedural | es werden die eingebauten (mysqli_connect, mysqli_query) oder benutzerdefinierten Funktionen (s.o. arrayAusgabe) einzeln programmiert und aufgerufen |
OOP | wir nutzen bestehende oder selbst definierte Klassen und Objekte modern, effizient - erspart Zeit |
Empfehlung: OOP ist moderner und effizienter - also letztlich unser Ziel für die Nutzung von MySQL-Datenbanken mittels PHP/MySQLi
OOP-Vorteile:
- Wiederverwendbarkeit
- Zeitersparnis beim Coden
- leichte Erweiterbarkeit
OOP-Nachteile:
- anfangs verwirrend (viele Begriffe und Techniken)
- mehr Aufwand als mal schnell eine Funktion zu schreiben
Sehen Sie hierzu auch meine ausführlicheren Darstellungen zu unseren "PHP & MySQL"-Seminaren.
Meinen Teilnehmern wurden die folgenden Übungsdatenbanken dargestellt.
Datenbank - Technik | Autor - Beschreibung |
---|---|
gaestebuch | Praxisbeispiel aus PHP und MySQL - Das Umfassende Handbuch Rheinwerk Verlag |
news | Dr. Florence Maurice - PHP 5.5 und MySQL 5.6 - dpunkt Verlag 2014 Kapitel 11 PHP & MySQL - Kap. 11.6 Prepared Statements - auf alles bestens vorbereitet Dr. Florence Maurice - PHP 7 und MySQL - dpunkt Verlag 2018 Kapitel 11 PHP & MySQL - Kap. 11.7 MySQL-Beispiel (mit Prep. Statements) siehe hierzu auch meine PHP & MySQL Bibliothek |
kontakte | Christian Wenz; Internet magazin 02/2008 - MySQL mit PHP "Der Datenturbo" Einführung in die Techniken OOP, mysqli, Prepared Statements |
mysqli_prepare | Eigene Übungen bzw. Tests (siehe DB books / books2) Konnektion mit Datenbank und Darstellung der OOP-Vorgehensweise gemäß PHP-Online-Tutorial |
Aus den Skriptbeispielen ergibt sich die vorliegende Kontakteverwaltung mit den folgenden Techniken:
- PHP mysqli mit OOP und Prepared Statement
- Fehler- und Ausnahmenbehandlungen mit try / catch Blöcken
Anm.: für die Funktionalität nicht wichtig - Link zu php.net Website - Einfachste Formularbehandlung
- Konzentration auf Darstellung Grundoperationen CRUD (Create, Read, Update, Delete)
Datenbank
Wir stellen uns die nötige Datenbank bereit. Für die vorliegende Kontaktverwaltung benötigen Sie einen XAMPP und die Datenbank phpmysql_kontakte.
Sie können sich natürlich eine eigene DB erstellen und müssen dann im DB-Include-Skript die Infos anpassen.
- Vorgehen: mit phpMyAdmin eine Datenbank
phpmysql_kontakte
erstellen;
danach Tabelle importieren mittelstabelle-kontakt-erstellen.sql
. - Alternative: gesamte Datenbank
phpmysql_kontakte
inklusive Tabellekontakt
mit beiliegenden SQL-Dumpdb-phpmysql_kontakte-tabelle-kontakt-erstellen.sql
in DB-Server importieren.
PHP-Skripte
Die beteiligten PHP-Skripte wurden ausgiebig kommentiert und werden hier als Code (bzw. Download) dargestellt.
db.inc.php
Datenbank konnektieren und mysqli-Objekt bereitstellen.{code lang:php showtitle:false lines:true hidden:false}<?php
// DB-Konnection und Fehlerbehandlung für Datenbankserver / Datenbank
$mysqli = new mysqli("localhost", "root", "", "phpmysql_kontakte");
if ($mysqli->connect_error) {
echo "Fehler bei der Verbindung: " . mysqli_connect_error();
exit();
}
if (!$mysqli->set_charset("utf8")) {
echo "Fehler beim Laden von UTF8 ". $mysqli->error;
}
?>{/code}
index.php
Aktuelle Kontaktverwaltung auslesen und anzeigen.{code lang:php showtitle:false lines:true hidden:false}<?php
// Einfügen der Datenbank-Konnektion (und ggf. Helfer-Klassen)
// Objekt für DB: mysqli (benannt wie die PHP-MySQLi-Klasse mysqli
require_once 'db.inc.php';
?>
<!DOCTYPE HTML>
<html lang="de-DE">
<head>
<meta charset="UTF-8">
<title>Kontakteverwaltung mit OOP (Prepared Statements)</title>
</head>
<body>
<table style="width: 500px;">
<thead> <!-- Tabellenkopf für Ausgabe Kontakte -->
<tr>
<th>Nr.</th> <th>Vorname</th> <th>Nachname</th> <th>E-Mail</th> <th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php
try { // Kapselungen in try/catch-Blöcke zur erweiterten Fehlerbehandlung
// Nutzen von MySQLi-Prepared-Statements Technik (Klasse: mysqli_stmt)
// SQL-SELECT vorbereiten - sortieren nach id - aufsteigend
if ($stmt = $mysqli->prepare("SELECT id, vorname, nachname, email FROM kontakt ORDER BY id ASC")) {
// Abfrage (Query) durchführen
$stmt->execute();
// Ergebnisse (Spalten) an eigene / definierte Variablen binden
$stmt->bind_result($id, $vorname, $nachname, $email);
// Mit Methode fetch() die Ergebnisse in Schleife durchlaufen / ausgeben
while($stmt->fetch()) {
echo "<tr>\n";
echo "<td><strong>" . $id . "</strong></td>"
. "<td>" . htmlspecialchars($vorname) . "</td>"
. "<td>" . htmlspecialchars($nachname) . "</td>"
. "<td>" . htmlspecialchars($email) . "</td>"
. "<td> <a href=\"bearbeiten.php?id=" . (int)$id . "\">bearbeiten</a>"
. "| <a href=\"loeschen.php?id=" . (int)$id . "\">löschen</a> </td>\n";
echo "</tr>\n";
} // end while
// Prepared Statement Objekt wieder freigeben
$stmt->close();
} // Ende der IF-Then-Anweisungen
// Datenbankverbindungsobjekt freigeben
$mysqli->close();
// Fehler mit try/catch abfangen/ausgeben
} catch (Exception $ex) {
echo '<tr><td colspan="5">Fehler!</td></tr>';
}
?>
</tbody>
</table>
<p>
<a href="/neu.php">Neuen Kontakt anlegen</a>
</p>
</body>
</html>{/code}
neu.php
Einen neuen Datensatz aufnehmen in Tabelle kontakt.{code lang:php showtitle:false lines:true hidden:false}<?php
require_once 'db.inc.php';
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Neu - Kontaktverwaltung</title>
</head>
<body>
<?php
// Formular validieren: (hier sehr einfach / grob)
// die Variablen vorname, nachname, email müssen
// alle per Methode Post übergeben worden sein und
// alle den Datentyp String besitzen und die email darf nicht leer sein!
if (isset($_POST['vorname']) && is_string($_POST['vorname']) &&
isset($_POST['nachname']) && is_string($_POST['nachname']) &&
isset($_POST['email']) && is_string($_POST['email']) && !empty($_POST['email'])) {
// wieder so eine try/catch Konstruktion zur Fehler-/Ausnahmebehandlung
try {
// Prepared Statement: Einfügen-SQL-String mit Platzhaltern (?)
$stmt = $mysqli->prepare('INSERT INTO kontakt (vorname, nachname, email) VALUES (?, ?, ?)');
// im Prepared Statement Objekt die übergebenen POST-Inhalte binden
$stmt->bind_param('sss', $_POST['vorname'], $_POST['nachname'], $_POST['email']);
// SQL Einfügen ausführen in IF-Bedingung, also: bei Erfolg
if ($stmt->execute()) {
// spezielle Methode des DB-Konnektions-Objekts nutzen
// Methode insert_id() ermittelt uns die neu erzeugte id des Datensatz
$id = $mysqli->insert_id;
// Infos zu neuem Datensatz (id) ausgeben, falls alles funktioniert hat
echo 'Kontakt eingetragen (ID: ' . $id . ')!';
} else {
echo 'Fehler: ' . htmlspecialchars($db->error) . '!</td></tr>';
}
// alle Objekte wieder freigeben
$stmt->close();
$mysqli->close();
// hier wieder der catch-Teil zur try/catch Technik
} catch (Exception $ex) {
echo 'Fehler!';
}
} // es folgt ein leeres HTML-Formular für neue Datensätze / Kontakte
?>
<form method="post" action="">
<table>
<thead>
<tr> <th>Information</th> <th>Wert</th> </tr>
</thead>
<tbody>
<tr>
<td>Vorname</td> <td><input type="text" name="vorname" /></td>
</tr>
<tr>
<td>Nachname</td> <td><input type="text" name="nachname" /></td>
</tr>
<tr>
<td>E-Mail</td> <td><input type="text" name="email" /></td>
</tr>
</tbody>
</table>
<input type="submit" value="Kontakt anlegen" />
</form>
<p> <a href="/index.php">Zur Startseite</a> </p>
</body>
</html>{/code}
loeschen.php
Einen Datensatz nach Rückfrage aus Tabelle kontakt löschen.{code lang:php showtitle:false lines:true hidden:false}<?php
require_once 'db.inc.php';
?>
<html>
<head>
<meta charset="UTF-8">
<title>Löschen - Kontaktverwaltung</title>
</head>
<body>
<?php
// Falls keine id per GET übergeben worden ist,
if (!isset($_GET['id'])) {
// dann bitte einfach direkt wieder auf index.php
header('Location: index.php');
// ansonsten, falls das POST-Feld ok nicht übergeben wurde
} elseif (!isset($_POST['ok'])) {
// setze Variable id auf Ganzzahl von per GET übergebene Variable id
$id = (int)$_GET['id'];
// Und wieder: try/catch Blöcke zur Fehler-/Ausnahmebehandlung
try {
// Prepared Statement: SQL-Select String für Datensatz mit GET-id
if ($stmt = $mysqli->prepare('SELECT id, vorname, nachname, email FROM kontakt WHERE id=?')) {
// Binde GET-id (als integer) an Prepared Statement
$stmt->bind_param("i", $id);
// Führe SQL-Select aus - Ergebnis für Datensatz liegt dann vor
$stmt->execute();
// Binde die folgenden Variablen an die Ergebnisse
$stmt->bind_result($id, $vorname, $nachname, $email);
// Hole uns die Ergebnisse
$stmt->fetch();
// Meldung / Feedback zum Löschdatensatz ausgeben
// hier wird jetzt verstecktes Form-Feld ok genutzt (type hidden)!
printf('Wollen Sie wirklich den Datensatz Nr. %s (%s %s, %s) löschen?<br />' .
'<form method="post" action=""><input type="hidden" name="ok" value="true" /><input type="submit" value="Löschen" /></form>',
(int) $id,
htmlspecialchars($vorname),
htmlspecialchars($nachname),
htmlspecialchars($email));
} else { // Falls es Fehler bei Prep-Stmt im ersten if gab:
echo 'Fehler: ' . htmlspecialchars($mysqli->error) . '!</td></tr>';
}
} catch (Exception $ex) { // catch zum try/catch-Block
echo 'Fehler!';
} // Ende catch-Teil
} else {
// Variable id aus Ganzzahl der per GET übergebenen Variable id
$id = (int)$_GET['id'];
// try/catch again
try {
// Prepared Statemen SQL-String Delete mit Platzhalter (?) bei where id
if ($stmt = $mysqli->prepare("DELETE FROM kontakt WHERE id=?")) {
// Platzhalter muss gebunden werden
$stmt->bind_param("i", $id);
// SQL ausführen
$stmt->execute();
// Objekte zurückgeben
$stmt->close();
$mysqli->close();
// Ausgabe / Quittung
echo 'Datensatz gelöscht!';
} else {
echo 'Fehler: ' . htmlspecialchars($mysqli->error) . '!</td></tr>';
}
} catch (Exception $ex) {
echo 'Fehler!';
}
}
?>
<p><a href="/index.php">Zur Startseite</a></p>
</body>
</html>{/code}
bearbeiten.php
Einen Datensatz zum Ändern / Aktualisieren bereitstellen und in Tabelle kontakt aktualisieren.{code lang:php showtitle:false lines:true hidden:false}<?php
require_once 'db.inc.php';
?>
<html>
<head>
<meta charset="UTF-8">
<title>Bearbeiten - Kontaktverwaltung</title>
</head>
<body>
<?php
// Falls keine id per GET übergeben worden ist,
if (!isset($_GET['id'])) {
// dann bitte einfach direkt wieder auf index.php
header('Location: index.php');
// ansonsten, "kleine" Validierung Formular:
// vorname, nachname, email müssen alle per POST übergeben sein!
} elseif (isset($_POST['vorname']) && isset($_POST['nachname']) && isset($_POST['email'])) {
try {
// Prepared Statement SQL-Befehl Update mit Platzhaltern
$stmt = $mysqli->prepare('UPDATE kontakt SET vorname=?, nachname=?, email=? WHERE id=?');
// Platzhalter binden mit 3 Strings und 1 integer Wert
$stmt->bind_param('sssi', $_POST['vorname'], $_POST['nachname'], $_POST['email'], $id);
// per GET übergebene hier wieder (siehe auch unten auf Variable id
$id = (int)$_GET['id'];
// SQL-Update ausführen und Meldung(en) erzeugen
if ($stmt->execute()) {
echo 'Kontakt aktualisiert!';
} else {
echo 'Fehler: ' . htmlspecialchars($mysqli->error) . '!</td></tr>';
}
// Statement Objekt zurückgeben
$stmt->close();
} catch (Exception $ex) {
echo 'Fehler!';
}
// ende von elseif
} else { // Falls keine POST-Variablen
// Variable id auf per GET übergebene Variable id setzen
$id = (int)$_GET['id'];
try { // und wieder try/catch Block - Beachten Bracket endet nicht vor HTML-Code!
// Prepared Statement: mit Select die Daten für den gewünschten Datensatz auslesen
// auch hier wird die geschweifte Klammer (Bracket) erst nach dem HTML-Code geschlossen!
if ($stmt = $mysqli->prepare("SELECT id, vorname, nachname, email FROM kontakt where id=?")) {
// Variable id an Prep Stmt Select binden
$stmt->bind_param("i", $id);
// SQL ausführen
$stmt->execute();
// Ergebnisse an gewünschte Variablen binden
$stmt->bind_result($id, $vorname, $nachname, $email);
// die Variablen holen
$stmt->fetch();
// es folgt das HTML-Formular... hier mit eingefügten Werten aus Select...
?>
<form method="post" action="">
<table>
<thead>
<tr>
<th>Information</th> <th>Wert</th>
</tr>
</thead>
<tbody>
<tr>
<td>Vorname</td>
<td><input type="text" name="vorname" value="<?php echo htmlspecialchars($vorname); ?>" /></td>
</tr>
<tr>
<td>Nachname</td>
<td><input type="text" name="nachname" value="<?php echo htmlspecialchars($nachname); ?>" /></td>
</tr>
<tr>
<td>E-Mail</td>
<td><input type="text" name="email" value="<?php echo htmlspecialchars($email); ?>" /></td>
</tr>
</tbody>
</table>
<input type="submit" value="Kontakt aktualisieren" />
</form>
<?php
} else {
echo 'Fehler: ' . htmlspecialchars($mysqli->error) . '!</td></tr>';
}
$mysqli->close();
} catch (Exception $ex) {
echo 'Fehler!';
}
}
?>
<p><a href="/index.php">Zur Startseite</a></p>
</body>
</html>{/code}
Wichtig: die hier dargestellten Codes sollen nur Technikprinzipien darstellen und ich gebe keinerlei Gewähr auf Funktion ode gar Sicherheit der Codezeilen.
Ihr Trainer Joe Brandes
Braunschweig, Mai 2017