Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Script Mods
 phpBB Adsense Mode

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 TLD Liste
 Webkatalog‑Verzeichnis

Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains und...
https://www.Hosterplus.de
Artfiles.de
Bietet Serviceorientierte Internetdienstleistungen...
https://www.Artfiles.de
 
 
 

PHP REST API erstellen: CRUD-Endpunkte mit PHP und MySQL

Sie befinden sich: Home > Php Tutorial > PHP REST API erstellen: CRU...

PHP REST API erstellen: CRUD-Endpunkte mit PHP und MySQL


Eintrag am:  29.04.2026
Hits / Besucher:  16
Sprache:  Deutsch
Kategorie:  Fortgeschrittene Tut...
Tutorial Art:  eigenes
Eingetragen von   schubertmedia schubertmedia
 
Beschreibung

Moderne Webanwendungen bestehen häufig aus einem Frontend, das über eine Schnittstelle mit dem Backend kommuniziert. Eine REST API bildet dabei die Brücke zwischen beiden Seiten. Sie nimmt HTTP-Anfragen entgegen, verarbeitet sie und liefert strukturierte JSON-Antworten zurück. PHP eignet sich hervorragend für den Aufbau solcher Schnittstellen, da es auf nahezu jedem Webserver verfügbar ist und mit PDO eine sichere Datenbankanbindung bietet. Dieses Tutorial zeigt Schritt für Schritt, wie eine vollständige REST API mit PHP und MySQL ohne Framework entsteht. Dabei werden alle vier CRUD-Operationen abgedeckt: Erstellen, Lesen, Aktualisieren und Löschen von Datensätzen.

Illustration zum Tutorial: PHP REST API erstellen: CRUD-Endpunkte mit PHP und MySQL

Zunächst klären wir die Grundprinzipien von REST und die Rolle der HTTP-Methoden.

Was ist eine REST API?

REST steht für „Representational State Transfer“ und beschreibt einen Architekturstil für verteilte Systeme. Eine REST API stellt Ressourcen über eindeutige URLs bereit und nutzt die Standard-HTTP-Methoden, um Operationen auf diesen Ressourcen auszuführen. Drei Grundprinzipien prägen diesen Ansatz: Zustandslosigkeit bedeutet, dass jeder Request alle notwendigen Informationen enthält. Eine einheitliche Schnittstelle sorgt dafür, dass alle Ressourcen nach dem gleichen Muster angesprochen werden. Die Ressourcenorientierung stellt sicher, dass jede Entität (zum Beispiel ein Benutzer) über eine eigene URL erreichbar ist.

Die vier wichtigsten HTTP-Methoden bilden das Fundament jeder REST API.

flowchart TD
    A["Client-Request"] --> B["index.php (Routing)"]
    B --> C{"HTTP-Methode?"}
    C -->|GET| D["Lesen"]
    C -->|POST| E["Erstellen"]
    C -->|PUT| F["Aktualisieren"]
    C -->|DELETE| G["Löschen"]
    D --> H["JSON-Antwort"]
    E --> H
    F --> H
    G --> H
    H --> I["Client erhält Antwort"]

GET ruft Daten ab, POST erstellt neue Datensätze, PUT aktualisiert bestehende Einträge und DELETE entfernt sie. Jede Antwort enthält einen HTTP-Statuscode, der den Erfolg oder Misserfolg der Operation signalisiert. Typische Statuscodes sind 200 für eine erfolgreiche Abfrage, 201 für eine erfolgreiche Erstellung, 400 für ungültige Anfragen und 404, wenn eine Ressource nicht gefunden wurde.

Projektstruktur für die PHP REST API

Bevor die erste Zeile Code geschrieben wird, sollte die Verzeichnisstruktur stehen. Ein klarer Aufbau erleichtert die Wartung und Erweiterung der API.

Für dieses Tutorial wird eine einfache Struktur mit einer zentralen Einstiegsdatei verwendet. Alle Requests werden über eine .htaccess-Datei an die index.php weitergeleitet. Diese Technik nennt sich URL-Rewriting und sorgt dafür, dass saubere URLs wie /api/benutzer/42 funktionieren.

<?php

/*
* Verzeichnisstruktur:
*
* api/
* .htaccess
* index.php
* config/
* database.php
*/

Die .htaccess-Datei leitet alle Anfragen, die nicht auf eine vorhandene Datei oder ein Verzeichnis zeigen, an die index.php weiter. Das Modul mod_rewrite muss dafür auf dem Apache-Server aktiviert sein.

<?php

/*
* Inhalt der .htaccess Datei:
*
* RewriteEngine On
* RewriteCond %{REQUEST_FILENAME} !-f
* RewriteCond %{REQUEST_FILENAME} !-d
* RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
*/

Der Query-Parameter path enthält anschließend den angeforderten Pfad. Aus einer Anfrage an /api/benutzer/5 wird so intern index.php?path=benutzer/5. Die index.php kann diesen Pfad dann auswerten und die passende Funktion aufrufen.

Die Datenbankverbindung mit PDO

Eine REST API arbeitet in den meisten Fällen mit einer Datenbank. PDO (PHP Data Objects) bietet eine sichere und flexible Möglichkeit, eine Verbindung zu MySQL herzustellen. Besonders wichtig sind dabei Prepared Statements, die vor SQL-Injection schützen.

<?php

/* config/database.php */

function datenbankVerbindung(): PDO
{
$host = 'localhost';
$dbname = 'api_tutorial';
$benutzer = 'root';
$passwort = '';

$dsn = "mysql:host=$host;dbname=$dbname;charset=utf8mb4";

$optionen = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];

return new PDO($dsn, $benutzer, $passwort, $optionen);
}

Die Option PDO::ERRMODE_EXCEPTION sorgt dafür, dass Datenbankfehler als Exceptions geworfen werden, anstatt stillschweigend zu scheitern. FETCH_ASSOC liefert Ergebnisse als assoziative Arrays. Die deaktivierten emulierten Prepared Statements stellen sicher, dass MySQL die Statements tatsächlich serverseitig vorbereitet. Als Datenbanktabelle dient eine einfache benutzer-Tabelle mit den Spalten id, name und email.

Einfaches Routing für API-Endpunkte

Das Routing bestimmt, welche Funktion bei welcher HTTP-Methode und welchem Pfad aufgerufen wird. Die index.php bildet den zentralen Einstiegspunkt und wertet sowohl die HTTP-Methode als auch den URL-Pfad aus.

<?php

/* index.php */

require_once __DIR__ . '/config/database.php';

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

/* Preflight-Requests für CORS beantworten */
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}

$pdo = datenbankVerbindung();

$methode = $_SERVER['REQUEST_METHOD'];
$pfad = trim($_GET['path'] ?? '', '/');
$teile = explode('/', $pfad);

$ressource = $teile[0] ?? '';
$id = $teile[1] ?? null;

if ($ressource === 'benutzer') {
switch ($methode) {
case 'GET':
$id ? benutzerLesen($pdo, $id) : benutzerListe($pdo);
break;
case 'POST':
benutzerErstellen($pdo);
break;
case 'PUT':
benutzerAktualisieren($pdo, $id);
break;
case 'DELETE':
benutzerLoeschen($pdo, $id);
break;
default:
http_response_code(405);
echo json_encode(['fehler' => 'Methode nicht erlaubt']);
}
} else {
http_response_code(404);
echo json_encode(['fehler' => 'Ressource nicht gefunden']);
}

Der Router zerlegt den Pfad in seine Bestandteile. Das erste Segment bestimmt die Ressource, das zweite eine optionale ID. Die CORS-Header sind notwendig, wenn die API von einer anderen Domain aufgerufen wird, beispielsweise von einem JavaScript-Frontend. Der OPTIONS-Preflight-Request wird mit dem Statuscode 204 (No Content) beantwortet, damit der Browser die eigentliche Anfrage senden kann.

CRUD-Endpunkte implementieren

Mit dem Routing als Grundgerüst lassen sich nun die einzelnen Endpunkte implementieren. Jede Funktion übernimmt eine bestimmte CRUD-Operation und gibt das Ergebnis als JSON zurück.

GET: Daten abrufen

Die GET-Methode dient zum Lesen von Daten. Zwei Varianten sind üblich: eine Liste aller Datensätze und ein einzelner Datensatz anhand seiner ID.

<?php

function benutzerListe(PDO $pdo): void
{
$stmt = $pdo->query('SELECT id, name, email FROM benutzer');
$benutzer = $stmt->fetchAll();

http_response_code(200);
echo json_encode($benutzer);
}

function benutzerLesen(PDO $pdo, string $id): void
{
$stmt = $pdo->prepare('SELECT id, name, email FROM benutzer WHERE id = ?');
$stmt->execute([$id]);
$benutzer = $stmt->fetch();

if (!$benutzer) {
http_response_code(404);
echo json_encode(['fehler' => 'Benutzer nicht gefunden']);
return;
}

http_response_code(200);
echo json_encode($benutzer);
}

Die Funktion benutzerListe() gibt alle Einträge zurück. benutzerLesen() verwendet ein Prepared Statement, um einen einzelnen Benutzer anhand der ID zu laden. Wird kein Eintrag gefunden, liefert die API den Statuscode 404 mit einer passenden Fehlermeldung.

POST: Neuen Datensatz erstellen

Der POST-Endpunkt nimmt JSON-Daten im Request-Body entgegen und legt einen neuen Datensatz in der Datenbank an.

<?php

function benutzerErstellen(PDO $pdo): void
{
$json = file_get_contents('php://input');
$daten = json_decode($json, true);

if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
echo json_encode(['fehler' => 'Ungültiges JSON im Request-Body']);
return;
}

if (empty($daten['name']) || empty($daten['email'])) {
http_response_code(400);
echo json_encode(['fehler' => 'Name und E-Mail sind Pflichtfelder']);
return;
}

$stmt = $pdo->prepare('INSERT INTO benutzer (name, email) VALUES (?, ?)');
$stmt->execute([$daten['name'], $daten['email']]);

http_response_code(201);
echo json_encode([
'id' => $pdo->lastInsertId(),
'nachricht' => 'Benutzer erfolgreich erstellt'
]);
}

Der Request-Body wird über php://input gelesen. Diese Funktion liefert den rohen Inhalt der Anfrage. Mit json_decode() wird der JSON-String in ein assoziatives Array umgewandelt. Vor dem Einfügen prüft die Funktion, ob das JSON gültig ist und ob die Pflichtfelder vorhanden sind. Der Statuscode 201 signalisiert, dass eine neue Ressource erfolgreich erstellt wurde.

PUT: Datensatz aktualisieren

Die PUT-Methode aktualisiert einen bestehenden Datensatz. Sie erwartet ebenfalls JSON-Daten im Request-Body und eine ID in der URL.

<?php

function benutzerAktualisieren(PDO $pdo, ?string $id): void
{
if (!$id) {
http_response_code(400);
echo json_encode(['fehler' => 'Keine ID angegeben']);
return;
}

$json = file_get_contents('php://input');
$daten = json_decode($json, true);

if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
echo json_encode(['fehler' => 'Ungültiges JSON im Request-Body']);
return;
}

if (empty($daten['name']) || empty($daten['email'])) {
http_response_code(400);
echo json_encode(['fehler' => 'Name und E-Mail sind Pflichtfelder']);
return;
}

$stmt = $pdo->prepare('UPDATE benutzer SET name = ?, email = ? WHERE id = ?');
$stmt->execute([$daten['name'], $daten['email'], $id]);

if ($stmt->rowCount() === 0) {
http_response_code(404);
echo json_encode(['fehler' => 'Benutzer nicht gefunden']);
return;
}

http_response_code(200);
echo json_encode(['nachricht' => 'Benutzer erfolgreich aktualisiert']);
}

Die Methode rowCount() gibt an, wie viele Zeilen betroffen waren. Ist der Wert 0, existiert kein Datensatz mit der angegebenen ID, und die API antwortet mit 404. Diese Prüfung ist wichtig, damit der Client eine klare Rückmeldung erhält.

DELETE: Datensatz löschen

Der DELETE-Endpunkt entfernt einen Datensatz anhand seiner ID aus der Datenbank.

<?php

function benutzerLoeschen(PDO $pdo, ?string $id): void
{
if (!$id) {
http_response_code(400);
echo json_encode(['fehler' => 'Keine ID angegeben']);
return;
}

$stmt = $pdo->prepare('DELETE FROM benutzer WHERE id = ?');
$stmt->execute([$id]);

if ($stmt->rowCount() === 0) {
http_response_code(404);
echo json_encode(['fehler' => 'Benutzer nicht gefunden']);
return;
}

http_response_code(200);
echo json_encode(['nachricht' => 'Benutzer erfolgreich gelöscht']);
}

Auch hier wird über rowCount() geprüft, ob tatsächlich ein Datensatz gelöscht wurde. Ohne diese Prüfung würde die API auch bei einer nicht vorhandenen ID den Statuscode 200 liefern, was den Client in die Irre führen könnte.

JSON-Antworten korrekt senden

Jede REST API muss ihre Antworten in einem einheitlichen Format liefern. Der Content-Type-Header teilt dem Client mit, dass die Antwort JSON enthält. Ohne diesen Header könnte der Client die Antwort falsch interpretieren.

Der Header Content-Type: application/json; charset=utf-8 wird im Router bereits global gesetzt und gilt damit für alle Endpunkte. Die HTTP-Statuscodes folgen einem klaren Schema: 200 steht für eine erfolgreiche Abfrage oder Aktualisierung, 201 für eine erfolgreiche Erstellung, 400 für fehlerhafte Eingaben, 404 für nicht gefundene Ressourcen und 405 für nicht erlaubte Methoden. Eine konsistente Verwendung dieser Codes erleichtert dem Frontend die Fehlerbehandlung erheblich.

Die API testen

Nach der Implementierung muss die API getestet werden. Das Kommandozeilenwerkzeug cURL eignet sich dafür besonders gut, da es alle HTTP-Methoden unterstützt und auf den meisten Systemen vorinstalliert ist.

<?php

/*
* Alle Benutzer abrufen (GET):
* curl -X GET http://localhost/api/benutzer
*
* Einzelnen Benutzer abrufen (GET):
* curl -X GET http://localhost/api/benutzer/1
*
* Neuen Benutzer erstellen (POST):
* curl -X POST http://localhost/api/benutzer
* -H "Content-Type: application/json"
* -d '{"name": "Max Mustermann", "email": "max@example.com"}'
*
* Benutzer aktualisieren (PUT):
* curl -X PUT http://localhost/api/benutzer/1
* -H "Content-Type: application/json"
* -d '{"name": "Max Muster", "email": "max.neu@example.com"}'
*
* Benutzer löschen (DELETE):
* curl -X DELETE http://localhost/api/benutzer/1
*/

Alternativ bietet sich das grafische Werkzeug Postman an. Es erlaubt das Speichern von Anfragen in Sammlungen und die übersichtliche Darstellung der JSON-Antworten. Für die Entwicklungsphase ist cURL auf der Kommandozeile oft schneller, während Postman bei komplexeren APIs mit vielen Endpunkten seine Stärken ausspielt.

Sicherheitsaspekte

Eine öffentlich erreichbare API muss gegen typische Angriffsvektoren abgesichert werden. Der wichtigste Schutz gegen SQL-Injection sind Prepared Statements, die in diesem Tutorial durchgängig verwendet werden. Darüber hinaus sollte die Eingabevalidierung immer serverseitig stattfinden. Die Funktion filter_var() kann E-Mail-Adressen und andere Formate prüfen, bevor sie in die Datenbank geschrieben werden.

CORS-Header sind unverzichtbar, wenn das Frontend auf einer anderen Domain läuft als die API. Ohne diese Header blockiert der Browser die Anfrage aus Sicherheitsgründen. In der Produktion sollte Access-Control-Allow-Origin nicht auf * stehen, sondern nur die tatsächlich erlaubten Domains enthalten.

Für produktive APIs empfiehlt sich zudem eine Authentifizierung, beispielsweise über API-Keys oder JSON Web Tokens (JWT). Ohne eine solche Absicherung ist die API für jeden im Internet frei zugänglich. Auch eine Ratenbegrenzung (Rate Limiting) schützt vor übermäßigen Anfragen und Missbrauch.

Fazit

Eine REST API mit PHP und MySQL lässt sich ohne Framework in wenigen Schritten aufbauen. Der zentrale Router in der index.php wertet die HTTP-Methode und den URL-Pfad aus und leitet die Anfrage an die passende Funktion weiter. PDO mit Prepared Statements sorgt für eine sichere Datenbankanbindung. Die vier CRUD-Endpunkte decken die typischen Operationen ab: GET zum Lesen, POST zum Erstellen, PUT zum Aktualisieren und DELETE zum Löschen. JSON als Austauschformat und konsistente HTTP-Statuscodes runden die Schnittstelle ab. Für produktive Anwendungen sollten zusätzlich Authentifizierung, Ratenbegrenzung und eine gründliche Eingabevalidierung implementiert werden. Wer die Grundlagen beherrscht, kann die API jederzeit um neue Ressourcen, Paginierung oder Filteroptionen erweitern.

 


Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.