Praktikumsversuch PHP
Dieses Praktikum dient der praktischen Erprobung von PHP.
Entwicklungsserver
Zum Testen der eigenen PHP-Programme kann ein lokaler Server verwendet werden (VSCode, XAMPP, php -S). Das fertige Programm kann über den Webserver der Fakultät Informatik/Mathematik genutzt werden.
Aufgabe 1: PHP-Datei erstellen
Erstellen Sie die Datei hallo.php mit folgendem Inhalt:
- HTML5-Gerüst mit einer Überschrift
- Ein Absatz mit der PHP-Ausgabe:
<?php echo date('d.m.Y'); ?>
Aufgabe 2: Formularverarbeitung
- Nutze das bereits erstellte Adress-Formular und konfiguriere dieses auf die HTTP-Methode POST und den Skriptnamen: ausgabe.php
- Erstelle die Datei ausgabe.php mit der Eigenschaft:
- Ausgabe der Feldinhalte
- Nutzung der Funktion: htmlspecialchars() gegen XSS-Angriffe
- Nutze:
var_dump() und print_r()für Debugging-Zwecke zusammen mit der Variable$_POSTbzw.$_POST["name"] - Sie können gern weitere Superglobals ausgeben wie z.B.
$_SERVERoder$_REQUEST
Aufgabe 3: Datenbanknutzung
Datenbank-Abstraktionsschicht PDO (PHP Data Objects)
- Wir nutzen die filebasierte Datenbank SQLite mit einer Anbindung mittels PDO (PHP Data Objects).
- Vorteil von PDO: einfacher Umstieg auf MySQL
- Extensions müssen aktiviert sein: extension=pdo, pdo_sqlite
- SQlite nutzt intern Unicode, der PDO-Treiber standardmäßig UTF-8, seit PHP 5.6 ist UTF-8 Standard
- mögliche Fehlermodi: Silent, Warning, Exception -> wir nutzen Exception -> Fehler abfangen mittels try … catch
- wichtige PDO-Funktionen:
- exec(string $sql): direkte Ausführung von Befehlen ohne Result (INSERT, UPDATE,…)
- query(string $sql): liefert PDOStatement als Ergebnis
- prepare(string $sql): Vorbereitung einer SQL-Anweisung
- execute(): vorbereitetes Statement ausführen, optional mit Parameterübergabe
- bindParam(): Bindet eine Variable
- bindValue(): Bindet einen konkreten Wert
- fetch(): liefert eine Zeile des PDOStatments
- fetchAll(): liefert alle Zeilen des PDOStatements
- beginTransaction(): ACID - Atomicity, Consistency, Isolation, Durability
- commit/rollBack schreibt alle Änderungen oder verwirft alle Änderungen
- lastInsertId(): letzte ID
- 👉 Zum Schutz gegen SQL-Injection sollten generell INSERT-Anweisungen durch PDO mit Prepared Statements ersetzt werden.
Grundlegenden SQL-Operationen (CRUD: Create, Read, Update, Delete):
SELECT: Daten aus einer Tabelle abfragen
Beispiel:SELECT * FROM Kunden;INSERT INTO: Neue Daten einfügen
Beispiel:INSERT INTO Kunden (Name, Stadt) VALUES ('Anna', 'Berlin');UPDATE: Bestehende Daten ändern
Beispiel:UPDATE Kunden SET Stadt = 'Hamburg' WHERE Name = 'Anna';DELETE FROM: Daten löschen
Beispiel:DELETE FROM Kunden WHERE Name = 'Anna';CREATE TABLE: Neue Tabelle erstellen
Beispiel:CREATE TABLE Kunden (ID INT, Name VARCHAR(50), Stadt VARCHAR(50));UPSERT: Daten einfügen oder ändern
Beispiel:INSERT INTO scores (name, points) VALUES (:name, :points) ON CONFLICT(name) DO UPDATE SET points = points + excluded.points;
Optionen
- Filter:
WHERE (Nachname="Maier" AND Vorname="Thomas") - Reihenfolge:
ORDER BY Nachname, Vorname DESC; -- absteigend - Anzahl:
LIMIT 10; -- nur die ersten 10 Zeilen
Codebeispiele für verschiedene Datenbankoperationen:
// absoluter Pfad des aktuellen Arbeitsverzeichnisses
$dbFile = __DIR__ . '/scores.db';
// Nutzung des PDP-Interfaces mit dem SQlite-Treiber
try {
$pdo = new PDO('sqlite:' . $dbFile);
// Options
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Exceptions on
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE=> PDO::FETCH_ASSOC); // fetch mit asssoziativem Array
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['error' => 'Datenbank‑Fehler: ' . $e->getMessage()]);
exit;
}
// Tabelle anlegen
// Heredoc‑Syntax mit Kennung SQL
$createTableSQL = <<<SQL
CREATE TABLE IF NOT EXISTS scores (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
points INTEGER NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
SQL;
$pdo->exec($createTableSQL);
// 1. Direktes Query (SELECT)
foreach ($pdo->query('SELECT id, name FROM users') as $row) {
echo $row['id'] . ': ' . $row['name'] . PHP_EOL;
}
// 2. Exec (INSERT/UPDATE/DELETE ohne Rückgabe)
$affected = $pdo->exec('DELETE FROM sessions WHERE expires < datetime(\'now\')');
// 3. Prepared Statement mit benannten Parametern
$stmt = $pdo->prepare('SELECT * FROM posts WHERE author = :author AND created > :date');
$stmt->execute([':author' => $author, ':date' => $date]);
$posts = $stmt->fetchAll(); // bereits assoziativ dank DEFAULT_FETCH_MODE
// 4. Transaktion
$pdo->beginTransaction();
try {
$pdo->exec('INSERT INTO orders (user_id,total) VALUES (1,99.95)');
$pdo->exec('UPDATE users SET balance = balance - 99.95 WHERE id = 1');
$pdo->commit();
} catch (PDOException $e) {
$pdo->rollBack();
throw $e; // oder loggen
}
// 5. Letzte Insert‑ID
$newId = $pdo->lastInsertId();
Aufgabe 3.1: Highscore per Formular
- Erstellen Sie ein PHP-Skript, welches folgende Daten entgegennimmt und in einer SQLite-Datenbank speichert:
- Name
- Punktanzahl
- Wenn ein Name nicht vorhanden ist, soll ein neuer Datenbankeintrag erzeugt werden
- Wenn ein Name schon vorhanden ist, sollen die Punkte addiert werden
- Das Skript soll die ersten 5 Einträge mit dem höchsten Punktestand per HTML-Ausgabe auflisten
Aufgabe 3.2: Highscore per Ajax
- Erweitern Sie die obige Aufgabe um einen asynchronen Zugriff
- Die Datenübergabe soll jeweils per JSON erfolgen
- Gesendete JSON-Daten müssen im Skript per
file_get_contents('php://input')geholt werden, da der Zugriff über die POST-Variable nur für die Codierung von Formularen (application/x-www-form-urlencoded) funktioniert.
Aufgabe 3.3 Highscore per REST-API
- Erweitern Sie das obige Beispiel mit einer REST-API.
- Steuerung des URL-Zugriffs mittels Apache/.htaccess.
- Vollziehen Sie dazu das unten stehende Beispiel nach.
- Achtung: Das api-Verzeichnis muss Leserechte für jeden haben
Beispiel für .htaccess
# Erlaube HTTP-Methoden
<Limit GET POST PUT DELETE OPTIONS HEAD>
Require all granted
</Limit>
RewriteEngine On
# Leitet Anfragen wie /api/users an index.php weiter
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L,QSA]
Beispiel für PHP-Skript
<?php
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Origin: *");
// Methode ermitteln (GET, POST, etc.)
$method = $_SERVER['REQUEST_METHOD'];
$request_uri = $_SERVER['REQUEST_URI'];
echo "Anfrage-Pfad: " . $request_uri;
// Beispieldaten (würden normalerweise aus einer DB kommen)
$users = [
["id" => 1, "name" => "Max Mustermann"],
["id" => 2, "name" => "Erika Musterfrau"]
];
switch ($method) {
case 'GET':
// Rückgabe aller Benutzer
echo json_encode($users);
break;
case 'POST':
// Neuen Benutzer empfangen (simuliert)
$input = json_decode(file_get_contents('php://input'), true);
if (!empty($input['name'])) {
http_response_code(201); // Created
echo json_encode(["message" => "Benutzer erstellt", "data" => $input]);
} else {
http_response_code(400); // Bad Request
echo json_encode(["error" => "Name fehlt"]);
}
break;
default:
http_response_code(405); // Method Not Allowed
echo json_encode(["error" => "Methode nicht erlaubt"]);
break;
}
?>