Erster Eintrag in eine MySQL-Datenbank mit PHP 1
3 4- Die Verbindung zur Datenbank herstellen
- Der Aufbau einer Datenbank-Tabelle
- Die Datenbank-Tabelle anlegen
- Die Daten einfügen, auslesen und bearbeiten
- MySQL-Fehlermeldungen anzeigen
- Die Daten über ein Formular sicher eintragen
- Die Daten über ein Formular bearbeiten
- Die Daten sortiert und begrenzt ausgeben
- Hinweise zu den MySQL-Anweisungen
4. Die Daten einfügen, auslesen und bearbeiten
Die Datenbank-Tabelle muss nun mit Daten gefüttert werden, diese Daten stammen meist aus Formularen die Benutzer ausfüllen.
Nach dem ausfüllen des Formulars werden diese Daten per PHP an die Datenbank-Tabelle gesendet und eingetragen,
hierfür benötigen Sie die MySQL-
INSERT
-Anweisung, die Sie gleich kennen lernen werden.
Es gibt im wesentlichen vier MySQL-Anweisungen:
INSERT
- Datensatz einfügenSELECT
- Datensatz auslesenUPDATE
- Datensatz überschreibenDELETE
- Datensatz löschen
Jede dieser Anfragen (im engl. als query
bezeichnet) wird über die Datenbanksprache
SQL (engl. Structured Query Language
= Strukturierte Abfragesprache) ausgeführt.
Nachfolgend gehe ich immer auf den weiter unten gezeigten Quelltext ein, wenn jemand meine Erklärung dazu nicht gleich
versteht macht das nichts, entweder noch einmal lesen oder den Quelltext studieren der recht einfach gehalten ist.
INSERT - Datensatz einfügen
Die PHP-Funktion exec()
führt eine Anweisung aus und gibt die Anzahl der
betroffenen Datensätze zurück und sollte für
INSERT
,
UPDATE
und
DELETE
-Anweisungen genutzt werden.
Mit INSERT INTO
fügen Sie einen neuen Datensatz ein, gefolgt von dem
Namen der Tabelle `nachrichten`
und den Spalten
`titel`, `autor`, `nachricht`, `datum`
.
Mit VALUES
fügen Sie dann den eigentlichen Inhalt in die Tabelle ein.
Bitte beachten Sie die Reihenfolge der Spalten (dies ist eine häufige Fehlerquelle) und hinter dem letzten Wert darf kein Komma
mehr stehen, sonst wird die Anweisung nicht ausgeführt.
1
2
3
4
5
6
7
8
9
10
11
<?php
// Verbindung zur Datenbank aufbauen.
include "verbinden.php";
// Datensatz einfügen.
if ($db->exec("INSERT INTO `nachrichten`
(`titel`, `autor`, `nachricht`, `datum`)
VALUES ('Hallo Welt!', 'Werner', 'Viel Text ...', '2023-05-30')")) {
echo '<p>Die Nachricht wurde eingetragen.</p>';
}
?>
Zu kompliziert, hier folgt eine wesentlich übersichtlichere Anweisung die ich immer bevorzuge.
Mit SET
, dem Namen der
Spalte einem Gleichheitszeichen und dem Inhalt der Spalte, wird ein Datensatz eingetragen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
// Verbindung zur Datenbank aufbauen.
include "verbinden.php";
// Datensatz einfügen.
if ($db->exec("INSERT INTO `nachrichten`
SET
`titel` = 'Hallo Welt!',
`autor` = 'Werner',
`nachricht` = 'Viel Text ...',
`datum` = '2023-05-30'")) {
echo '<p>Die Nachricht wurde eingetragen.</p>';
}
?>
➤ Die Daten die eingetragen werden, sollten hierbei vom PHP-Programm selbst kommen und nicht vom Benutzer über ein Formular „manipuliert” sein. Siehe » Die Daten über ein Formular sicher eintragen weiter unten auf dieser Seite.
➤ Es müssen bei allen Feldern (außer der ID), die in der Datenbank-Tabelle sind und die nicht in dem INSERT angesprochen werden von vorne herein Vorgabewerte angegeben werden.
SELECT - Datensatz (Datensätze) auslesen
Mit der PHP-Funktion query()
kann man Daten aus der DB-Tabelle auslesen.
Mit SELECT `titel`, `name`, `nachricht`, `datum`
in der MySQL-Anweisung, wählen Sie die gewünschten
Spalten der Tabelle zum lesen aus, gefolgt von FROM
und dem Namen der Tabelle
`nachrichten`
.
Die PHP-Funktion fetchAll()
gibt der Variable $nachrichten
ein Array
mit allen Folgesätzen zurück. Mit einer foreach()
-Schleife werden die Datensätze dann über
$var['Spalten_Name']
ausgegeben.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// Verbindung zur Datenbank aufbauen.
include "verbinden.php";
// Datensätze auslesen.
$select = $db->query("SELECT `titel`, `autor`, `nachricht`, `datum`
FROM `nachrichten`");
$nachrichten = $select->fetchAll();
// Ausgabe über eine Foreach-Schleife.
foreach ($nachrichten as $nachricht) {
echo '<p>' . $nachricht["titel"] . '<br>' .
$nachricht["autor"] . '<br>' .
$nachricht["nachricht"] . '<br>' .
$nachricht["datum"] . '</p>';
}
?>
Das folgende Beispiel zeigt das auslesen wenn der Parameter
PDO::FETCH_OBJ
(Klassen-interne Konstante) bei fetchAll(…)
hinzugefügt wird, es wird dann ein Objekt mit allen Datensätzen zurück gegeben.
Die Ausgabe erfolgt dann über einer foreach()
-Schleife mit $var->SpaltenName
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// Verbindung zur Datenbank aufbauen.
include "verbinden.php";
// Datensätze auslesen.
$select = $db->query("SELECT `titel`, `autor`, `nachricht`, `datum`
FROM `nachrichten`");
$nachrichten = $select->fetchAll(PDO::FETCH_OBJ);
// Ausgabe über eine Foreach-Schleife.
foreach ($nachrichten as $nachricht) {
echo '<p>' . $nachricht->titel . '<br>' .
$nachricht->autor . '<br>' .
$nachricht->nachricht . '<br>' .
$nachricht->datum . '</p>';
}
?>
⚑ Nur einen Datensatz auslesen
Manchmal benötigt man nur einen bestimmten Datensatz aus einer DB-Tabelle, deshalb ist da
eine foreach()
-Schleife unnötig.
Mit der Spalte `id` in der Tabelle, hat jeder Datensatz eine eindeutige Identifikationsnummer, diese kann man nun dazu benutzen einen bestimmten Datensatz auszulesen. Es könnte auch eine Kundennummer, E-Mail-Adresse oder ein Benutzername sein. Die Hauptsache ist, das der Wert einmalig in der Spalte vorkommt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
// Verbindung zur Datenbank aufbauen.
include "verbinden.php";
// Einen Datensatz auslesen.
$select = $db->query("SELECT `titel`, `nachricht`
FROM `nachrichten`
WHERE `id` = 7");
// $select->fetch() holt die betreffende Zeile aus dem Ergebnis der Anfrage.
$datensatz = $select->fetch();
// Mit $select->rowCount() überprüfen ob ein Datensatz zurückgegeben wurde.
if ($select->rowCount() == 1) {
// Ausgabe
echo '<p>' . $datensatz["titel"] . ' - ' . $datensatz["nachricht"] . '</p>';
}
?>
Mit WHERE
weisen Sie
an welcher Datensatz ausgelesen werden soll. In diesem Beispiel wird `id` = '7'
,
also der Datensatz mit dem Identifikationsnummer 7 ausgelesen.
$datensatz = $select->fetch()
holt die betreffende Zeile aus dem Ergebnis der Anfrage.
Und $select->rowCount()
enthält die Anzahl der zurückgegeben Datensätze.
⚑ Filter
Mit der WHERE
-Klausel (Bedingung) können Sie die Auswahl der Daten bei einem SELECT
filtern.
Angenommen Sie möchten nur die Nachrichten anzeigen die in der Spalte `kategorie` den Eintrag Software
haben,
dann lautet die MySQL-Anweisung wie folgt:
1
2
3
4
5
6
<?php
// Datensätze auslesen.
$select = $db->query("SELECT `titel`, `autor`, `nachricht`, `datum`
FROM `nachrichten`
WHERE `kategorie` = 'Software'");
?>
⚑ Limitierung
Die Anzahl der Nachrichten können Sie mit der LIMIT
-Anweisung limitieren (begrenzen).
Dazu fügen Sie nach LIMIT
den Wert ein ab welchem Datensatz die Nachrichten ausgelesen werden
(5
), nach dem Komma folgt dann die Anzahl der Nachrichten (10
) die
ausgelesen werden sollen, also: LIMIT 5,10
.
1
2
3
4
5
6
<?php
// Datensätze auslesen.
$select = $db->query("SELECT `titel`, `autor`, `nachricht`, `datum`
FROM `nachrichten`
LIMIT 5,10");
?>
Mit der Anweisung LIMIT 12
(ohne einem zweiten Wert) wird das auslesen auf 12 Datensätze limitiert.
➤ Wie die LIMIT-Anweisung und dessen Werte nun dazu benutzt werden um eine Seiten-Navigation (Pagination) zu erstellen, erfahren Sie auf der nächsten Seite unter » Die Daten sortiert und begrenzt ausgeben
UPDATE - Datensatz überschreiben
Mit UPDATE
überschreiben Sie einen Datensatz, gefolgt von dem Namen der Tabelle
`nachrichten`
und SET
dahinter geben Sie die
Spalte an, die Sie überschreiben möchten und dessen Inhalt. Mit WHERE
weisen Sie
an welcher Datensatz geändert werden soll. In diesem Beispiel wird `id` = '17'
,
also der Datensatz mit der Identifikationsnummer (ID) 17 geändert.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
// Verbindung zur Datenbank aufbauen.
include "verbinden.php";
// Datensatz überschreiben.
if ($db->exec("UPDATE `nachrichten`
SET
`titel` = 'Hallo Welt die zweite!',
`nachricht` = 'Viel mehr Text ...'
WHERE
`id` = '17'")) {
echo '<p>Die Nachricht wurde überschrieben.</p>';
}
?>
➤
Achtung: Wenn keine WHERE
-Klausel (Bedingung) angegeben wird, so werden alle Datensätze überschrieben!
DELETE - Datensatz löschen
Mit DELETE FROM
löschen Sie einen Datensatz, gefolgt von dem
Namen der Tabelle `nachrichten`
und WHERE
weisen Sie an welchen Datensatz Sie löschen möchten. In diesem Beispiel wird `id` = '35'
, also der Datensatz
mit der Identifikationsnummer 35 gelöscht.
1
2
3
4
5
6
7
8
9
10
<?php
// Verbindung zur Datenbank aufbauen.
include "verbinden.php";
// Datensatz löschen.
if ($db->exec("DELETE FROM `nachrichten`
WHERE `id` = '35'")) {
echo '<p>Die Nachricht wurde gelöscht.</p>';
}
?>
➤
Achtung: Wenn keine WHERE
-Klausel
angegeben wird, werden alle Datensätze der Tabelle ohne Nachfrage gelöscht!
⚠
Beachten Sie, dass es bei einer Datenbank keinen „Rückgängig-Button” gibt, wie Sie ihn vielleicht von Word oder Excel gewohnt sind.
Eine DB-Tabelle stellt einen elementaren Datenspeicher dar,
INSERT
, UPDATE
oder DELETE
verändern diesen Speicher direkt.
Und was Sie eingefügt, geändert oder gelöscht haben, ist unwiderruflich eingefügt, geändert oder gelöscht.
✔ Nicht jeder Datensatz muss gleich gelöscht werden, fügen Sie eine Tabellenspalte hinzu die den Datensatz auf "inaktiv" setzt, so kann dieser leicht zurück geholt werden.
Siehe auch: Löschen von mehreren Einträgen aus einer DB-Tabelle
5. MySQL-Fehlermeldungen anzeigen
Nicht nur PHP kann Fehler enthalten sondern auch die MySQL-Anweisung. Um nun nicht wild zu raten wo der Fehler in der
MySQL-Anweisung versteckt ist, bauen wir ein
if(){} else{}
-Statement ein das den Fehler abfängt und dann mit
$db->errorInfo()
eine detaillierte Fehlermeldung ausgibt.
Wir haben oben, bei der Verbindung zur Datenbank,
bereits eine Option hinzugefügt die eine Fehlermeldung für PDO aktiviert: PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
.
Nun muss bei einer fehlerhaften MySQL-Anweisung diese Fehlermeldung auch ausgegeben werden.
Das folgende Script enthält einen Fehler in der MySQL-Anweisung 9 , es wurde ein Komma am Ende der Zeile vergessen!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
// Verbindung zur Datenbank aufbauen.
include "verbinden.php";
// Datensatz überschreiben.
// Zeile 9 enthält einen Fehler, es wurde ein Komma vergessen!
if ($db->exec("UPDATE `nachrichten`
SET
`titel` = 'Hallo Welt die zweite!'
`nachricht` = 'Viel mehr Text ...'
WHERE
`id` = '17'")) {
// Bei einer erfolgreichen Änderung (UPDATE) wird 'true' zurück gegeben.
echo '<p>Die Nachricht wurde überschrieben.</p>';
}
else {
// Andernfalls wird (bei 'false') eine SQL-Fehlermeldung ausgegeben.
print_r($db->errorInfo());
}
?>
Nach dem aufrufen im Browser wird folgende MySQL-Fehlermeldung ausgegeben:
Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax
to use near '`nachricht` = 'Viel mehr Text ...' WHERE ' at line 4 )
Die Zahl 42000 ist der SQLSTATE-Fehlercode, die Zahl 1064 ist der Fehlercode der aktuellen Fehlermeldung. Die Fehlermeldung weist uns noch freundlich darauf hin das man einen Fehler in der MySQL-Syntax hat und man in das Handbuch (MySQL-Referenzhandbuch) für die richtige Syntax schauen sollte.
Wichtig ist, was weiter unten steht: near '`nachricht` = 'Viel mehr Text ...' WHERE '
, zeigt die fehlerhafte Syntax an und
at line 4
die entsprechende Zeile wo der Fehler dem MySQL-Parser aufgefallen ist (wobei der eigentliche Fehler meist eine Zeile höher liegt).
Für Schreibfaule geht das auch einfacher mit dem
or die()
-Statement.
1
2
3
4
5
6
7
8
<?php
$db->exec("UPDATE `nachrichten`
SET
`titel` = 'Hallo Welt die zweite!'
`nachricht` = 'Viel mehr Text ...'
WHERE
`id` = '17'") or die($db->errorInfo()[2]);
?>
➤ Man sollte schon beim schreiben der MySQL-Anweisung darauf achten diese in mehrere Zeilen aufzuteilen und Einrückungen (Leerzeichen, Tabulatoren) einsetzen. Die Anweisung lässt sich schnell auf eventuelle Fehler überprüfen und es wird bei einer Fehlermeldung die betreffende Zeile mit ausgegeben, siehe » Quelltext mit Format.
➤
Wenn bei PHP die Anzeige von Fehlermeldungen (mit error_reporting(E_ALL);
) aktiviert sind,
dann kann eine fehlerhafte MySQL-Anweisung, auch bei PHP eine Fehlermeldung auslösen, zum Beispiel:
Fatal error: Uncaught Error: Call to a member function fetchAll() on bool in …
6. Die Daten über ein Formular sicher eintragen
Sicheres Programmieren – Traue niemals den Eingaben des Benutzers!
Hier folgt ein Beispiel wie Daten sicher in die Datenbank-Tabelle über ein Formular eingetragen werden können.
Grundsätzlich sollten Formulareingaben immer als Angriff auf das Formular der Website angesehen werden!
Bisher war es immer ein großes Problem wenn Eingaben über ein Formular gemacht wurden, häufig kam es zu SQL-Injektionen. Die DB-Tabelle konnte über ein Formular kompromittiert werden, Passwörter und anderes konnten ausgelesen und die Tabelle konnte schlimmstenfalls komplett gelöscht werden.
Nachfolgend sehen Sie zwei Beispiele wie man es nicht machen sollte:
<?php
// Fehler! - Die POST-Variablen stehen direkt im SQL-Code.
$insert = $db->exec("INSERT INTO `nachrichten`
SET
`titel` = $_POST[titel],
`autor` = $_POST[autor],
`nachricht` = $_POST[nachricht],
`kategorie` = $_POST[kategorie],
`anzeige` = $_POST[anzeige],
`datum` = NOW()");
// Fehler! - Die GET-Variablen stehen direkt im SQL-Code.
$insert = $db->exec("DELETE FROM `nachrichten` WHERE `id` = $_GET[id]");
?>
Mit den „Prepared Statements” (zu deutsch: vorbereitete Anweisung) ist dies nun vorbei, die Daten die über POST/GET gesendet wurden, werden über Platzhalter (zum Beispiel: :titel :autor :nachricht :kategorie :anzeige) in den SQL-Code eingeführt.
<?php
$insert = $db->prepare("INSERT INTO `nachrichten`
SET
`titel` = :titel,
`autor` = :autor,
`nachricht` = :nachricht,
`kategorie` = :kategorie,
`anzeige` = :anzeige,
`datum` = NOW()");
$insert->bindValue(':titel', $_POST["titel"]);
$insert->bindValue(':autor', $_POST["autor"]);
$insert->bindValue(':nachricht', $_POST["nachricht"]);
$insert->bindValue(':kategorie', $_POST["kategorie"]);
$insert->bindValue(':anzeige', $anzeige);
// ...
?>
Die Platzhalter werden mit der Funktion: bindValue()
durch den Inhalt der POST-Variablen ersetzt und maskiert.
$insert->bindValue(':nachricht', $_POST["nachricht"]);
Später zeige ich noch, wie sich die Platzhalter (einfacher und auch sicher) über ein Array einfügen lassen.
➤ Es sollten nicht nur die Eingaben von Textfeldern/Textbereichen durch Platzhalter ersetzt werden, sondern auch von Auswahllisten, Checkboxen, Radiobuttons usw. da diese auch manipuliert sein können.
Sämtliche potentiell gefährlichen Anweisungen in Platzhaltern werden automatisch maskiert und sind somit ungefährlich. Daher sollten Sie immer „Prepared Statements” einsetzen, anstatt PHP-Variablen in Ihre MySQL-Anweisung einzubauen. So ist Ihre Web-Anwendung von dieser Seite aus nicht angreifbar und der Aufwand für diesen erheblichen Gewinn an Sicherheit ist minimal.
Dieses Bildschirmfoto zeigt das Formular zum eintragen einer Nachricht an.
Quelltext: eintragen.php Ausblenden ❘ Kopieren ❘ Link ❘ Zeilen ❘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Nachricht eintragen</title>
<style>
body {
font-family: Verdana, Arial, Sans-Serif;
background-color: Whitesmoke;
}
a:link, a:visited {
color: Royalblue;
text-decoration: None;
}
</style>
</head>
<body>
<nav>
<a href="auslesen.php">Nachrichten</a> |
<u>Eintragen</u> |
<a href="bearbeiten.php">Bearbeiten</a> |
<a href="suchen.php">Suchen</a>
</nav>
<form action="eintragen.php" method="post">
<p>
<label>Titel:
<input type="text" name="titel" size="45" maxlength="80" required="required" autofocus="autofocus">
</label>
</p>
<p>
<label>Autor:
<input type="text" name="autor" size="25" maxlength="30" required="required">
</label>
</p>
<p>
<label>Kategorie:
<select name="kategorie" size="1" required="required">
<option>Aktuell</option>
<option>Hardware</option>
<option>Software</option>
</select>
</label>
</p>
<p>
<label>Nachricht:<br>
<textarea rows="10" cols="40" name="nachricht" required="required"></textarea>
</label>
</p>
<p>
<label>
<input type="checkbox" name="anzeige"> Nachricht anzeigen
</label>
</p>
<p>
<input type="submit" value="Absenden">
</p>
</form>
<?php
// Wurde das Formular abgesendet?
if ("POST" == $_SERVER["REQUEST_METHOD"]) {
/* Die Formulareingaben müssen hier überprüft werden,
siehe: https://werner-zenk.de/php/php_mit_sicherheit.php */
/* Verbindung zur Datenbank aufbauen.
Die Verbindung sollte erst aufgebaut werden, wenn diese benötigt wird. */
include "verbinden.php";
/* Der Variable $anzeige einen Wert zuweisen, entweder 1 oder 0.
Je nachdem ob die Checkbox gesetzt (ausgewählt) wurde. */
$anzeige = isset($_POST["anzeige"]) ? 1 : 0;
/* Nachricht eintragen
prepare() (prepare = aufbereiten) bereitet die Anweisung für die Ausführung vor.
Die Platzhalter werden hier anstatt den POST-Variablen eingesetzt. */
$insert = $db->prepare("INSERT INTO `nachrichten`
SET
`titel` = :titel,
`autor` = :autor,
`nachricht` = :nachricht,
`kategorie` = :kategorie,
`anzeige` = :anzeige,
`datum` = NOW()");
/* Die Platzhalter werden mit $insert->bindValue() durch den
Inhalt der POST-Variablen ersetzt und maskiert. */
$insert->bindValue(':titel', $_POST["titel"]);
$insert->bindValue(':autor', $_POST["autor"]);
$insert->bindValue(':nachricht', $_POST["nachricht"]);
$insert->bindValue(':kategorie', $_POST["kategorie"]);
$insert->bindValue(':anzeige', $anzeige);
/* $insert->execute() führt die vorbereitete Anweisung aus.
Bei einem erfolgreichen Eintrag wird 'true' zurück gegeben. */
if ($insert->execute()) {
echo '<p>▷ Die Nachricht wurde eingetragen.</p>';
/* Um die gerade eingetragene Nachricht bearbeiten zu können, benötigen
wir die ID des zuletzt eingetragenen Datensatzes: lastInsertId() */
$id = $db->lastInsertId();
// Nun hängen wir an den Dateinamen (bearbeiten.php) die ID dran
echo '<p><a href="bearbeiten.php?id=' . $id . '">Nachricht bearbeiten</a></p>';
}
else {
// Andernfalls (bei 'false') wird eine SQL-Fehlermeldung ausgegeben.
print_r($insert->errorInfo());
}
}
?>
</body>
</html>
➤ Um das Script hier möglichst einfach zu halten, werden die Formulareingaben des Benutzers nicht validiert (überprüft), Zeile 75. Dies müssen Sie selbst einbauen wenn Sie das Script im produktiven Einsatz verwenden wollen. Siehe: PHP mit Sicherheit
Nachdem die ersten Einträge in der Tabelle stehen, schaut diese ungefähr so aus:
id | titel | autor | nachricht | kategorie | anzeige | datum |
---|---|---|---|---|---|---|
1 | Hallo Welt! | Werner | Viel Text ... | Aktuell | 1 | 2023-05-28 |
2 | Lorem Ipsum | Blindtextchen | Weit hinter den … | Aktuell | 0 | 2023-05-29 |
3 | Testtext | Testi | Testext um den Text … | Software | 1 | 2023-05-30 |
So, nun müssen fleißig weitere Daten eingetragen werden, damit auch welche
ausgegeben werden können