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 - TechnikAutor - 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 mittels tabelle-kontakt-erstellen.sql  .
  • Alternative: gesamte Datenbank phpmysql_kontakte inklusive Tabelle kontakt mit beiliegenden SQL-Dump db-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&ouml;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