15.2 Einführende Beispiele (prozedural)

Die folgende Include-Datei beinhaltet die Parameter für die Verbindung zum MySQL-Datenbank-Server. Diese Datei sollte aus Sicherheitsgründen klarererweise nicht im öffentlichen Webserverbereich gespeichert sein!

Include-Datei dbConnectDaten.inc.php
<?php $servername = "localhost"; $dbBenutzer = "root"; $dbPasswort = ""; ?>


Die folgende Include-Datei beinhaltet eine Funktion für das Verbinden zum MySQL-Datenbank-Server. Diese Funktion wird in allen nachfolgenden prozeduralen Programmen verwendet.

Include-Datei dbConnectFunktion.inc.php
<?php function dbConnect($servername, $dbBenutzer, $dbPasswort, $datenbank) { // Die Verbindung zum Datenbank-Server herstellen $verbindung = mysqli_connect($servername, $dbBenutzer, $dbPasswort) or die("Die Verbindung zum MySQL-Server auf <b>$servername</b> ist fehlgeschlagen! " . mysqli_error($verbindung)); // Eine Datenbank auswählen mysqli_select_db($verbindung, $datenbank) or die("Die Auswahl der Datenbank <b>$datenbank</b> ist fehlgeschlagen! " . mysqli_error($verbindung)); return $verbindung; } ?>


15.2.1 Einfache Statements - Funktion mysqli_query

Datei pDB-01.php
<!doctype html> <!-- Programm "pDB-01.php" --> <html> <head> <meta charset="iso-8859-1" /> <meta name="author" content="Beringer Alfred" /> <meta name="description" content="Programmieren mit PHP 5" /> <title>Zugriff auf MySQL-Datenbank (prozedural)</title> </head> <body> <pre>
<?php const DATENBANK = "schueler"; // Pfad zum privaten Projektverzeichnis (siehe Kap.16.1.2) require_once "projektpfad.inc.php"; require_once PFAD . "prozeduraleSkripte/Includedateien/dbConnectDaten.inc.php"; require_once PFAD . "prozeduraleSkripte/Includedateien/dbConnectFunktion.inc.php"; $verbindung = dbConnect($servername, $dbBenutzer, $dbPasswort, DATENBANK); $sqlBefehl = "SELECT name, notenschnitt, klasse FROM schueler "; // ----------------------------------------------------------------------------- // SQL-Befehl durchführen $resultat = mysqli_query($verbindung, $sqlBefehl) or die("Die Anfrage '<b>$sqlBefehl</b>' ist fehlgeschlagen! " . mysqli_error($verbindung)); // ----------------------------------------------------------------------------- // Nur zum Testen: // Die Anzahl der Zeilen und Spalten der Abfrage ausgeben. echo "<p>************************************************************************</p>"; echo "<p>Die Anzahl der Zeilen und Spalten der Abfrage ausgeben (nur zum Testen):</p>"; $anzahl = mysqli_num_rows($resultat); echo "<p>Es wurden <b>$anzahl</b> Datens&auml;tze (bzw. Zeilen) gefunden.</p>"; $anzahl = mysqli_num_fields($resultat); echo "<p>Jede Zeile besteht aus <b>$anzahl</b> Datenfeldern (bzw. Spalten).</p>"; echo "<p>************************************************************************</p>"; // ----------------------------------------------------------------------------- // Alle Zeilen lesen und ausgeben - Zugriff über assoziatives Array $zeile = mysqli_fetch_array($resultat); while ($zeile) { print($zeile["name"] . " "); print($zeile["notenschnitt"] . " "); print($zeile["klasse"] . "<br />"); $zeile = mysqli_fetch_array($resultat); } // ----------------------------------------------------------------------------- // Die Verbindung zum Datenbank-Server schließen mysqli_close($verbindung); ?>
</pre> <p> </p><hr /><p> </p> <footer> <address id="ende"> Copyright &#169; 2009<br /> Letzte Aktualisierung: 2013-10-30<br /> Beringer Alfred<br /> Wögerer Wolfgang </address> </footer> </body> </html>
Bem.:
Die Ausgabe der ersten 3 Zeilen dient nur zum Testen.
Die Daten aus der Datenbank wurden der Einfachheit halber nicht übersichtlich aufbereitet.
Die Zahlenwerte für den Notendurchschnitt kommen direkt aus der Datenbank und entsprechen daher genau den Werten des SQL-INSERT-Befehls (siehe Kap.15.1.1). Man vergleiche dazu die Ausgabe des nachfolgenden Programms.


15.2.2 Prepared Statements - Funktion mysqli_stmt_execute

Ein SQL-Befehl wird vor Durchführung eingehend nach verschiedenen Kriterien (u.a. natürlich auf korrekte Syntax) geprüft. Wird der Befehl mehrmals durchgeführt, werden jedesmal dieselben Prüfungen gemacht. Es gibt jedoch die Möglichkeit, einen SQL-Befehl als 'Prepared Statement' zu definieren. Dabei wird der Befehl ein einziges Mal (vor der ersten Durchführung) geprüft und - falls alle Prüfungen positiv ausfallen - intern gespeichert. Danach kann der Befehl beliebig oft ohne weitere Prüfung durchgeführt werden. Es ist sogar möglich, ein "Prepared Statement" zu parametrisieren.

Der Geschwindigkeitsvorteil eines "Prepared Statement" gegenüber einem einfachen Statement liegt auf der Hand. Es gibt aber einen noch viel gewichtigeren Vorteil: Durch "Prepared Statements" werden sog. SQL-Injections verhindert!

Es gibt eine ganze Reihe von mysqli-Funktionen für "Prepared Statements". Der Aufwand für 'Prepared Statements' ist zwar ein wenig größer, aber die praktischen Vorteile überwiegen bei weitem!

Datei pDB-02.php
<!doctype html> <!-- Programm "pDB-02.php" --> <html> <head> <meta charset="iso-8859-1" /> <meta name="author" content="Beringer Alfred" /> <meta name="description" content="Programmieren mit PHP 5" /> <title>Zugriff auf MySQL-Datenbank - Prepared Statement (prozedural)</title> </head> <body> <pre>
<?php const DATENBANK = "schueler"; // Pfad zum privaten Projektverzeichnis (siehe Kap.16.1.2) require_once "projektpfad.inc.php"; require_once PFAD . "prozeduraleSkripte/Includedateien/dbConnectDaten.inc.php"; require_once PFAD . "prozeduraleSkripte/Includedateien/dbConnectFunktion.inc.php"; $verbindung = dbConnect($servername, $dbBenutzer, $dbPasswort, DATENBANK); $sqlBefehl = "SELECT name, notenschnitt, klasse FROM schueler "; // ----------------------------------------------------------------------------- // Prepared Statement erzeugen $prepStat = mysqli_prepare($verbindung, $sqlBefehl) or die("Prepared-Statement '<b>$sqlBefehl</b>' konnte nicht erzeugt werden! " . mysqli_error($verbindung)); // ----------------------------------------------------------------------------- // Prepared Statement durchführen mysqli_stmt_execute($prepStat) or die("Anfrage '<b>$sqlBefehl</b>' fehlgeschlagen! " . mysqli_error($verbindung)); // ----------------------------------------------------------------------------- // Puffern des Resultats mysqli_stmt_store_result($prepStat); // ----------------------------------------------------------------------------- // Nur zum Testen: // Die Anzahl der Zeilen und Spalten der Abfrage ausgeben. echo "<p>************************************************************************</p>"; echo "<p>Die Anzahl der Zeilen und Spalten der Abfrage ausgeben (nur zum Testen):</p>"; $anzahl = mysqli_stmt_num_rows($prepStat); echo "<p>Es wurden <b>$anzahl</b> Datens&auml;tze (bzw. Zeilen) gefunden.</p>"; $anzahl = mysqli_stmt_field_count($prepStat); echo "<p>Jede Zeile besteht aus <b>$anzahl</b> Datenfeldern (bzw. Spalten).</p>"; echo "<p>************************************************************************</p>"; // ----------------------------------------------------------------------------- // Selektierte Spalten an Variable binden (Zuordnung: Spalte - Variable) mysqli_stmt_bind_result($prepStat, $name, $notenschnitt, $klasse); // ----------------------------------------------------------------------------- // Alle Zeilen lesen und ausgeben - Zugriff über gebundene Variable $ok = mysqli_stmt_fetch($prepStat); while ($ok != null && $ok) { print($name . " "); print($notenschnitt . " "); print($klasse . "<br />"); $ok = mysqli_stmt_fetch($prepStat); } // ----------------------------------------------------------------------------- // Die Verbindung zum Datenbank-Server schließen mysqli_close($verbindung); ?>
</pre> <p> </p><hr /><p> </p> <footer> <address id="ende"> Copyright &#169; 2009<br /> Letzte Aktualisierung: 2013-10-30<br /> Beringer Alfred<br /> Wögerer Wolfgang </address> </footer> </body> </html>
Bem.:
Die Zahlenwerte für den Notendurchschnitt kommen nun aus einer PHP-Variablen vom Typ Float! Man vergleiche dazu die Ausgabe des vorhergehenden Programms.
Die Dezimalzahlen 1,4 und 2,35 haben im Zweiersystem unendlich viele duale Nachkommastellen (siehe Kap.8.1.3)!


Wie aus diesem Programm ersichtlich sind die folgenden Schritte bei Verwendung von "Prepared Statements" notwendig:

Anschließend kann das Prepared Statement beliebig oft durchgeführt werden:

  1. Gegebenenfalls Parameter durch Argumente ersetzen (Funktion 'mysqli_stmt_bind_param' )
  2. Dabei müssen die Datentypen der Argumentvariablen definiert werden - es gibt 4 mögliche Typen:
    s
    korrespondierendes Argument ist eine Zeichenkette (String)
    i
    korrespondierendes Argument ist eine ganze Zahl (Integer)
    d
    korrespondierendes Argument ist eine rationale Zahl (Float)
    b
    korrespondierendes Argument sind binäre Daten

  3. Prepared Statement durchführen (Funktion 'mysqli_stmt_execute' )
  4. Optional: Speichern (puffern) des Resultats (Funktion 'mysqli_stmt_store_result' )
    (dies erhöht die Geschwindigkeit und ist notwendig für Informationen über das Resultat (z.B. Anzahl Zeilen))
  5. Selektierte Spalten an Variable binden (Funktion 'mysqli_stmt_bind_result' )
  6. Zeilen einzeln verarbeiten (Funktion 'mysqli_stmt_fetch' )
Bem.:
Die Funktion 'mysqli_prepare' vereint die beiden Funktionen 'mysqli_stmt_init' und 'mysqli_stmt_prepare' .

Der Vorteil von "Prepared Statements" zeigt sich vor allem bei der Parametrisierung von SQL-Befehlen.


Das folgende Beispiel fordert in einem Formular die Angabe einer Klasse und eines Notendurchschnitts, danach werden alle Schüler der ausgewählten Klasse, deren Notendurchschnitt kleiner als der vorgegebene Wert ist, ausgegeben.

Datei pDB-03.html
<!doctype html> <!-- HTML-Datei "pDB-03.html" --> <html> <head> <meta charset="iso-8859-1" /> <meta name="author" content="Beringer Alfred" /> <meta name="description" content="Programmieren mit PHP 5" /> <title>Zugriff auf MySQL-Datenbank - Prepared Statement mit Parametern (prozedural)</title> </head> <body> <form name="formEingabe" action="pDB-03.php" method="post" accept-charset="iso-8859-1"> <p> Bitte geben Sie die gew&uuml;nschten Auswahlparameter ein<br /> (ausgegeben werden alle Sch&uuml;ler bzw. Sch&uuml;lerinnen, deren Notendurchschnitt kleiner oder gleich ist): </p> <p> <table> <tr> <td>Klasse:</td> <td><input type="text" name="fTxfKlasse" /></td> </tr> <tr> <td>Notendurchschnitt:</td> <td><input type="text" name="fTxfNotenschnitt" /></td> </tr> </table> </p> <p> <input type="submit" name="fButOk" value=" OK " /> <input type="reset" name="fButReset" value="Zur&uuml;cksetzen" /> </p> </form> <p> </p><hr /><p> </p> <footer> <address id="ende"> Copyright &#169; 2009<br /> Letzte Aktualisierung: 2013-10-30<br /> Beringer Alfred<br /> Wögerer Wolfgang </address> </footer> </body> </html>


Datei pDB-03.php
<!doctype html> <!-- Programm "pDB-03.php" --> <html> <head> <meta charset="iso-8859-1" /> <meta name="author" content="Beringer Alfred" /> <meta name="description" content="Programmieren mit PHP 5" /> <title>Zugriff auf MySQL-Datenbank - Prepared Statement mit Parametern (prozedural)</title> </head> <body> <pre>
<?php const DATENBANK = "schueler"; // Pfad zum privaten Projektverzeichnis (siehe Kap.16.1.2) require_once "projektpfad.inc.php"; require_once PFAD . "prozeduraleSkripte/Includedateien/dbConnectDaten.inc.php"; require_once PFAD . "prozeduraleSkripte/Includedateien/dbConnectFunktion.inc.php"; // ***************************************************************************** // Wenn Programm direkt (d.h. nicht über das Formular) aufgerufen wurde -> Ende if (empty($_POST)) { exit("Sie m&uuml;ssen dieses Programm &uuml;ber das entsprechende Formular aufrufen!"); } // ***************************************************************************** $verbindung = dbConnect($servername, $dbBenutzer, $dbPasswort, DATENBANK); // ----------------------------------------------------------------------------- // Parameter für SQL-Befehl aus dem Formular übernehmen $vklasse = $_POST["fTxfKlasse"]; $vnotenschnitt = $_POST["fTxfNotenschnitt"]; // ----------------------------------------------------------------------------- // SELECT-Befehl mit 2 Parametern definieren $sqlBefehl = "SELECT name, notenschnitt, klasse FROM schueler " . "WHERE klasse = ? AND notenschnitt < ? "; // ----------------------------------------------------------------------------- // Prepared Statement erzeugen $prepStat = mysqli_prepare($verbindung, $sqlBefehl) or die("Prepared-Statement '<b>$sqlBefehl</b>' konnte nicht erzeugt werden! " . mysqli_error($verbindung)); // ----------------------------------------------------------------------------- // Formale Parameter ('?') durch Argumente ersetzen (Reihenfolge wesentlich!) mysqli_stmt_bind_param($prepStat, "sd", $vklasse, $vnotenschnitt); // ----------------------------------------------------------------------------- // Prepared Statement durchführen mysqli_stmt_execute($prepStat) or die("Anfrage '<b>$sqlBefehl</b>' fehlgeschlagen! " . mysqli_error($verbindung)); // ----------------------------------------------------------------------------- // Puffern des Resultats mysqli_stmt_store_result($prepStat); // ----------------------------------------------------------------------------- // Selektierte Spalten an Variable binden (Zuordnung: Spalte - Variable) mysqli_stmt_bind_result($prepStat, $name, $notenschnitt, $klasse); // ----------------------------------------------------------------------------- // Alle Zeilen lesen und in einer HTML-Tabelle ausgeben // Den Kopf der HTML-Tabelle definieren print("<table border='1'>"); print("<tr>"); print("<th bgcolor='#BBBBBB'>Name des Schülers</th>"); print("<th bgcolor='#BBBBBB'>Notendurchschnitt</th>"); print("<th bgcolor='#BBBBBB'>Klasse</th>"); print("</tr>"); // Alle Zeilen der Query-Tabelle lesen und in die HTML-Tabelle einfügen // Zugriff über gebundene Variable $ok = mysqli_stmt_fetch($prepStat); while ($ok != null && $ok) { print("<tr>"); print("<td> $name </td>"); print("<td> $notenschnitt </td>"); print("<td> $klasse </td>"); print("</tr>"); $ok = mysqli_stmt_fetch($prepStat); } // Das Ende der HTML-Tabelle definieren print("</table>"); // ----------------------------------------------------------------------------- // Die Verbindung zum Datenbank-Server schließen mysqli_close($verbindung); ?>
</pre> <p> </p><hr /><p> </p> <footer> <address id="ende"> Copyright &#169; 2009<br /> Letzte Aktualisierung: 2013-10-30<br /> Beringer Alfred<br /> Wögerer Wolfgang </address> </footer> </body> </html>



Weiter zu
Kapitel 15.3 - Beispiel mit Datenerfassung (Datenbanken, objektorientiert)
Kapitel 16.1.2 - Projektpfad - Include-Datei "projektpfad.inc.php"
Zurück
zum Anfang dieses Kapitels
zu Kapitel 3.2.1.2 - Programm 1 (prozedural)
zu Kapitel 3.2.2.2 - Programm 2 (prozedural)
zu Kapitel 3.2.3.2 - Programm 3 (prozedural)
zu Kapitel 4.2.1.2 - Programm 1 (objektorientiert)
zu Kapitel 4.2.2.2 - Programm 2 (objektorientiert)
zu Kapitel 4.2.3.2 - Programm 3 (objektorientiert)
zu Kapitel 8.7.1 - Demo-Programm (Werte- und Referenztypen)
zu Kapitel 9.1.4 - Demo-Programm (Parameterübergabe)
zu Kapitel 14.2 - Beispiel mit Datenerfassung (Dateien, objektorientiert)
zu Kapitel 15.1.1 - SQL-Skript
zum Inhaltsverzeichnis