MB Dev .tech
Registrieren Login

PHP + DB Praxis · Soft Delete

← Zurück zu PHP + DB Praxis

„Löschen“ klingt simpel – ist in echten Systemen aber oft heikel. Wenn Daten einmal wirklich weg sind, kannst du sie nicht mehr anzeigen, nicht mehr wiederherstellen und oft auch nicht mehr nachvollziehen, was passiert ist.

Deshalb gibt es ein sehr häufiges Muster: Soft Delete. Dabei wird ein Datensatz nicht wirklich gelöscht, sondern nur als „gelöscht“ markiert.

Merke
Soft Delete = verstecken statt zerstören

Der Datensatz bleibt in der Datenbank, taucht aber in normalen Listen nicht mehr auf.

1) Hartes Löschen vs. Soft Delete

Es gibt zwei grundlegende Varianten:

  • Hard Delete: DELETE FROM table ... → Daten sind weg.
  • Soft Delete: UPDATE setzt ein Flag / Datum → Daten bleiben.
Achtung
Hard Delete ist endgültig

Selbst wenn du Backups hast: Wiederherstellen ist aufwendig und manchmal gar nicht möglich, wenn andere Daten inzwischen weitergelaufen sind.

2) Wie baut man Soft Delete in eine Tabelle ein?

Es gibt mehrere Varianten. Zwei sehr gängige:

  • is_deleted (0/1) als Flag
  • deleted_at als Datum/Zeit (NULL = nicht gelöscht)

Die deleted_at-Variante ist oft praktischer, weil du auch siehst, wann etwas gelöscht wurde.

SQL (Tabelle erweitern)

ALTER TABLE tasks
  ADD deleted_at DATETIME NULL;
Tipp
NULL = nicht gelöscht

Das ist leicht zu merken und gut in SQL zu filtern: WHERE deleted_at IS NULL

3) Soft Delete ausführen (UPDATE statt DELETE)

Statt den Datensatz zu löschen, setzt du das Feld deleted_at auf „jetzt“.

Soft Delete (UPDATE)

$taskId = 5;

$sql  = "UPDATE tasks SET deleted_at = NOW() WHERE id = :id";
$stmt = $pdo->prepare($sql);

$stmt->execute([
    ':id' => $taskId,
]);
Achtung
UPDATE ohne WHERE ist auch hier gefährlich

Ohne WHERE würdest du alle Datensätze „löschen“ – und sie wären in der App plötzlich weg.

4) Wichtiger Schritt: Abfragen müssen es berücksichtigen

Soft Delete bringt nur etwas, wenn du in deinen SELECT-Abfragen gelöschte Einträge ausblendest. Sonst erscheinen sie weiterhin in der Liste.

SELECT (nur nicht gelöschte)

$sql = "
  SELECT id, title, created_at
  FROM tasks
  WHERE deleted_at IS NULL
  ORDER BY created_at DESC
";
Merke
Soft Delete ist ein Abfrage-Filter

Du „schaltest“ gelöschte Datensätze aus, indem du sie in jeder relevanten Abfrage ausschließt.

5) Wiederherstellen (Undo / Restore)

Der große Vorteil von Soft Delete: Du kannst Daten zurückholen. Dafür setzt du deleted_at wieder auf NULL.

Restore

$taskId = 5;

$sql  = "UPDATE tasks SET deleted_at = NULL WHERE id = :id";
$stmt = $pdo->prepare($sql);

$stmt->execute([
    ':id' => $taskId,
]);
Tipp
„Papierkorb“-Ansicht

Viele Apps bauen eine extra Liste: „Gelöschte Einträge“ (WHERE deleted_at IS NOT NULL), und erlauben dort „Wiederherstellen“ oder „endgültig löschen“.

6) Typische Fehler bei Soft Delete

  • SELECT-Abfragen vergessen den Filter (deleted_at IS NULL)
  • Detailseiten zeigen „gelöschte“ Datensätze noch an
  • Unique-Constraints kollidieren (z.B. E-Mail ist „gelöscht“, aber noch vorhanden)
Achtung
Soft Delete ist kein Ersatz für Rechte/Security

Nur weil etwas „gelöscht“ ist, heißt das nicht automatisch, dass niemand mehr darauf zugreifen kann. Deine App muss trotzdem sauber prüfen, was angezeigt werden darf.

Kleine Aufgaben (zum Mitdenken)

Aufgabe 1: Filter ergänzen

Du hast eine Liste mit SELECT * FROM tasks. Welche Bedingung musst du ergänzen, damit gelöschte Einträge nicht erscheinen?

Lösung einblenden
Lösung
WHERE deleted_at IS NULL

Damit blendest du alle Einträge aus, die ein Lösch-Datum haben.