Eine solide Laravel cache-Strategie ist oft der schnellste praktische Performance-Gewinn, den man einer Anwendung verschaffen kann. Jeder Datenbank-Roundtrip, jeder externe API-Aufruf und jedes schwere Seiten-Rendering kostet Zeit; diese Ergebnisse einmal zu berechnen und zu speichern, statt sie bei jeder Anfrage neu zu ermitteln, kann die Antwortzeiten auf Millisekunden senken. In diesem Leitfaden behandle ich Cache-Treiber, das Cachen von Queries und Seiten sowie das kritischste Thema überhaupt — die sichere Invalidierung des Caches — anhand praktischer Beispiele.
Wann hilft Caching wirklich?
Caching glänzt bei Daten, die teuer zu erzeugen sind, sich aber selten ändern. Typische Kandidaten sind:
- Reporting-Queries mit schweren
JOINs oder Aggregationen, - Menüs, Einstellungen oder Kategorielisten, die auf jeder Seite erscheinen,
- langsame oder limitierte externe API-Antworten (Wechselkurse, Wetter),
- HTML-Ausgabe ganzer Seiten, die sich selten ändert.
Im Gegensatz dazu sind benutzerspezifische Daten, die sofort korrekt sein müssen (Warenkorb-Saldo, Zahlungsstatus), meist das Falsche zum Cachen. Die erste Regel lautet: zuerst messen. Cache die Stelle, von der du nachgewiesen hast, dass sie langsam ist.
Den richtigen Treiber wählen
Die Cache-Schicht von Laravel ist treiberunabhängig; die Konfiguration liegt in config/cache.php, und der Standard-Store wird durch die Variable CACHE_STORE in deiner .env-Datei bestimmt. Die wichtigsten Optionen sind:
- file — keine Einrichtung, geeignet für kleine Single-Server-Projekte.
- database — Persistenz ohne zusätzlichen Dienst; gut bei moderater Last.
- redis / memcached — die empfohlene Wahl bei hohem Traffic, mehreren Servern und Tag-Unterstützung.
- array — lebt nur für eine einzige Anfrage; praktisch in Tests.
Wenn du in der Produktion ernsthaften Traffic erwartest, ist Redis fast immer die richtige Antwort. Die Konfiguration sieht so aus:
# .env
CACHE_STORE=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
Query-Caching: das remember-Muster
Die meistgenutzte API ist Cache::remember(): Sie gibt den Wert zurück, wenn der Schlüssel existiert, andernfalls führt sie die Closure aus, speichert das Ergebnis und gibt es zurück. Damit schrumpft die Logik „liefere, falls vorhanden, sonst berechne und speichere" auf eine einzige Zeile.
use Illuminate\Support\Facades\Cache;
$beliebt = Cache::remember('projects:beliebt', now()->addHour(), function () {
return Project::where('is_published', true)
->orderByDesc('views')
->take(10)
->get();
});
Die Dauer kann ein DateTime sein (now()->addHour()) oder eine Anzahl von Sekunden. Soll der Wert nie ablaufen, verwende Cache::rememberForever() — dann liegt die Invalidierung jedoch vollständig in deiner Verantwortung.
Es gibt auch Helfer auf niedrigerer Ebene:
Cache::put('schluessel', $wert, now()->addMinutes(10));
$wert = Cache::get('schluessel', 'standard');
Cache::has('schluessel');
Cache::forget('schluessel');
Cache::increment('besuchs_zaehler');
Ganzseiten- und Fragment-Caching
Wenn Query-Caching nicht ausreicht, kannst du auch gerendertes HTML speichern. Ein einfaches Muster auf Controller-Ebene:
public function index()
{
$html = Cache::remember('home:html', now()->addMinutes(15), function () {
return view('site.index', $this->ladeDaten())->render();
});
return response($html);
}
Möchtest du die gesamte Antwort auf HTTP-Ebene cachen, ist das in einer Middleware sauberer: Verwende die Request-URL als Schlüssel, prüfe sie mit Cache::has() und erzeuge und speichere die Antwort, falls sie fehlt. Auf statischen Showcase-Seiten senkt dieser Ansatz die Datenbanklast nahezu auf null.
Tags und sichere Invalidierung
Das Schwierige am Caching ist nicht das Speichern, sondern die Invalidierung zum richtigen Zeitpunkt. Wird ein Projekt aktualisiert, musst du alle zugehörigen Cache-Schlüssel löschen. Nutzt du Redis oder Memcached, machen Tags das elegant:
Cache::tags(['projects'])->put('projects:beliebt', $daten, 3600);
// Wenn sich ein Projekt ändert:
Cache::tags(['projects'])->flush();
Tags werden von den Treibern file und database nicht unterstützt; lösche die Schlüssel in diesem Fall manuell. Die robusteste Methode ist, sich in die Model-Events einzuklinken:
// Im Project-Model
protected static function booted(): void
{
static::saved(fn () => Cache::forget('projects:beliebt'));
static::deleted(fn () => Cache::forget('projects:beliebt'));
}
Über die Kommandozeile, um den gesamten Anwendungs-Cache zu leeren:
php artisan cache:clear
Config-, Route- und View-Caches
Es gibt eine separate Schicht, die nicht mit dem Caching von Anwendungsdaten verwechselt werden sollte: die framework-eigenen Caches. Auf einem Produktionsserver bringt das Ausführen dieser Befehle nach dem Deployment einen echten Geschwindigkeitsschub:
php artisan config:cache
php artisan route:cache
php artisan view:cache
# alles auf einmal:
php artisan optimize
Wichtiger Hinweis: Wenn config:cache aktiv ist, funktionieren env()-Aufrufe nur innerhalb von Konfigurationsdateien zuverlässig. Rufe env() nicht direkt im Code auf — lies Werte über config(). Wenn du die Konfiguration änderst, baue sie mit php artisan config:clear neu auf.
Häufige Fragen
Warum erscheinen meine Änderungen während der Entwicklung nicht?
Höchstwahrscheinlich wird dir ein veralteter Cache ausgeliefert. Der Befehl php artisan optimize:clear leert Config-, Route-, View- und Anwendungs-Cache in einem Rutsch; das ist das Erste, was du ausprobierst, wenn lokal etwas seltsam aussieht.
Sollte ich file oder Redis verwenden?
Für eine kleine Single-Server-Seite ist der file-Treiber mehr als ausreichend. Wechsle zu Redis, wenn du hohen Traffic, mehrere Server, atomare Zähler oder tag-basierte Invalidierung brauchst.
Wie lang sollte die Cache-TTL sein?
Das hängt davon ab, wie veraltet die Daten sein dürfen. Für Listen, die sich stündlich ändern, sind 15–60 Minuten sinnvoll; für Daten, die sich fast nie ändern, ist rememberForever() plus event-basierte Invalidierung am effizientesten.
Willst du die Performance mit einem gut durchdachten Cache zum Fliegen bringen? Lass uns gemeinsam die langsamen Stellen deiner Laravel-Anwendung messen und die richtige Caching-Strategie aufbauen — nimm Kontakt mit mir auf.