Datenbankabfragen und Aufrufe externer APIs sind CPU- und netzwerkintensiv und können mehrere Sekunden dauern.
Wenn Sie dieselben Daten wiederholt abrufen, können Sie das Ergebnis in einem Cache ablegen und nachfolgende Anfragen so deutlich beschleunigen.Laravel bietet eine einheitliche API für viele verschiedene Cache-Backends, darunter Memcached, Redis, DynamoDB und relationale Datenbanken.
Standardmäßig ist der Treiber database konfiguriert. Durch einen Wechsel zu Redis oder Memcached lässt sich der Cache noch weiter beschleunigen.
Speichert serialisierte Cache-Daten in einer Datenbanktabelle.
Ab Laravel 11 ist die passende Migration in neuen Projekten bereits enthalten.
CACHE_STORE=database
Fehlt die Migration, erzeugen Sie sie über einen Artisan-Befehl.
php artisan make:cache-tablephp artisan migrate
file
Speichert Cache-Daten im Dateisystem.
Er benötigt keine zusätzliche Einrichtung und eignet sich für kleinere Anwendungen.
CACHE_STORE=file
redis
Ein schneller, im Arbeitsspeicher laufender Cache-Treiber.
Er wird in der Produktion am häufigsten eingesetzt und benötigt entweder die PHP-Erweiterung PhpRedis oder das Paket predis/predis.
Der Treiber array ist ein In-Memory-Cache, der nur innerhalb eines Requests gültig ist.
null ignoriert alle Operationen. Beide sind für automatisierte Tests nützlich.
put() legt einen Wert im Cache ab. Der dritte Parameter ist die Gültigkeitsdauer in Sekunden.
// 10 Sekunden lang speichernCache::put('key', 'value', 10);// Gültigkeit über eine Carbon-Instanz angebenCache::put('key', 'value', now()->plus(minutes: 10));// Ohne Gültigkeitsdauer (dauerhaft speichern)Cache::put('key', 'value');
Mit add() speichern Sie nur, wenn der Schlüssel noch nicht existiert.
// Nur hinzufügen, wenn nicht vorhanden (atomare Operation)Cache::add('key', 'value', $seconds);
Für ein dauerhaftes Speichern verwenden Sie forever().
Das ist die am häufigsten verwendete Operation. Ist der Wert im Cache vorhanden, wird er zurückgegeben; andernfalls wird die Closure ausgeführt und ihr Ergebnis gespeichert.
$users = Cache::remember('users', 3600, function () { return DB::table('users')->get();});
Mit Cache::remember() fassen Sie die drei Schritte „Cache prüfen → bei Cache-Miss abrufen → im Cache speichern” in einer einzigen Zeile zusammen. Ideal zum Cachen von Datenbank-Ergebnissen und Antworten externer APIs.
Es gibt auch rememberForever() für dauerhaftes Speichern.
$value = Cache::rememberForever('users', function () { return DB::table('users')->get();});
Möchten Sie wissen, ob es ein Cache-Treffer oder ein frisch berechneter Wert war, verwenden Sie rememberWithWarmth(). Die Methode liefert ein Array mit dem Cache-Wert und einem Boolean, der angibt, ob der Wert „frisch” aus dem Cache stammt.
[$value, $warm] = Cache::rememberWithWarmth('users', 3600, function () { return DB::table('users')->get();});if ($warm) { // Daten stammen aus dem Cache} else { // Daten wurden von der Closure neu ermittelt}
rememberWithWarmth() eignet sich, um die Effizienz Ihres Caches zu beobachten. Ist $warm häufig false, können Sie die Gültigkeitsdauer (TTL) möglicherweise anpassen.
Stale While Revalidate (flexible Cache-Aktualisierung)
Cache::flexible() erwartet ein Array aus zwei Zeitfenstern: „frisch” und „veraltet, aber noch verwendbar”.
Nutzern werden ggf. veraltete Daten zurückgegeben, während der Cache im Hintergrund aktualisiert wird.
// [Dauer als frisch (Sek.), Dauer als noch nutzbar (Sek.)]$value = Cache::flexible('users', [5, 10], function () { return DB::table('users')->get();});
// Einzelnen Schlüssel löschenCache::forget('key');// Gesamten Cache leerenCache::flush();
Cache::flush() löscht unabhängig von einem eingestellten Cache-„Präfix” alle Einträge. Wenn Sie sich einen Cache mit mehreren Anwendungen teilen, ist Vorsicht geboten.
Mit Cache::flushLocks() können Sie alle atomaren Locks im Cache entfernen.
Mit dem Treiber memo werden Cache-Zugriffe innerhalb eines einzigen Requests im Speicher zwischengespeichert.
Damit vermeiden Sie überflüssige Roundtrips zum Cache-Store, wenn derselbe Schlüssel mehrfach abgefragt wird.
use Illuminate\Support\Facades\Cache;// Standard-Store memoisieren$value = Cache::memo()->get('key');// Redis-Store memoisieren$value = Cache::memo('redis')->get('key');
// Der erste Zugriff geht an den Cache-Store$value = Cache::memo()->get('key');// Ab dem zweiten Zugriff wird der Wert aus dem Speicher zurückgegeben (kein Store-Zugriff)$value = Cache::memo()->get('key');
// Alle Einträge mit den Tags 'people' UND 'authors' löschen (löscht John und Anne)Cache::tags(['people', 'authors'])->flush();// Nur den Tag 'authors' löschen (nur Anne; John bleibt erhalten)Cache::tags('authors')->flush();
Tags sind hilfreich, wenn Sie den Cache pro Gruppe – etwa pro Benutzer oder pro Beitrag – invalidieren möchten.
Beispiel: Mit Cache::tags(['user', "user:{$userId}"])->flush() leeren Sie alle Cache-Einträge zu einer Benutzerin oder einem Benutzer.
Mit Cache::lock() implementieren Sie verteilte Locks, um Race Conditions zwischen Prozessen oder parallelen Anfragen zu vermeiden.
Dieses Feature steht bei den Cache-Treibern memcached, redis, dynamodb, database, file und array zur Verfügung. Alle Server müssen mit demselben zentralen Cache-Server kommunizieren.
Wartet bis zu der angegebenen Anzahl an Sekunden, bis der Lock erworben werden kann. Bei einem Timeout wird LockTimeoutException ausgelöst.
use Illuminate\Contracts\Cache\LockTimeoutException;$lock = Cache::lock('foo', 10);try { $lock->block(5); // Maximal 5 Sekunden warten // Verarbeitung nach Erwerb des Locks} catch (LockTimeoutException $e) { // Lock konnte nicht erworben werden} finally { $lock->release();}
Mit einer Closure ist der Code kompakter.
Cache::lock('foo', 10)->block(5, function () { // Erwerben Sie den Lock mit bis zu 5 Sekunden Wartezeit; er wird nach Abschluss automatisch freigegeben});
Ein einfacher Weg, um zu verhindern, dass derselbe Prozess mehrfach parallel läuft.
Cache::withoutOverlapping('foo', function () { // Wird zeitgleich nur einmal ausgeführt});// Wartezeit und Lock-Haltezeit anpassenCache::withoutOverlapping('foo', function () { // ...}, lockFor: 120, waitFor: 5);
Begrenzt die Anzahl gleichzeitig ausführbarer Verarbeitungen.
Cache::funnel('foo') ->limit(3) // Bis zu 3 parallele Ausführungen zulassen ->releaseAfter(60) // Nach 60 Sekunden automatisch freigeben ->block(10) // Bis zu 10 Sekunden warten ->then(function () { // Verarbeitung, wenn ein Slot verfügbar war }, function () { // Verarbeitung, wenn kein Slot verfügbar war });
Erwerben Sie einen Lock in einem Web-Request und geben Sie ihn in einem Queue-Job wieder frei.
// Lock im Request erwerben und den Job dispatchen$lock = Cache::lock('processing', 120);if ($lock->get()) { ProcessPodcast::dispatch($podcast, $lock->owner());}// Lock innerhalb des Queue-Jobs freigebenCache::restoreLock('processing', $this->owner)->release();
Um einen Lock unabhängig vom aktuellen Owner erzwungen freizugeben, verwenden Sie die Methode forceRelease.
Um die Gültigkeitsdauer eines gerade gehaltenen Locks zu verlängern, verwenden Sie die Methode refresh. Ohne Angabe einer Dauer wird die ursprüngliche Gültigkeitsdauer erneut verwendet. Nützlich, wenn Sie einen kurzen Lock während einer langen Verarbeitung regelmäßig verlängern möchten, ohne von Anfang an eine sehr lange Gültigkeit setzen zu müssen.
$lock = Cache::lock('generate-reports', 60);if ($lock->get()) { foreach ($reports as $report) { $report->generate(); // Lock um weitere 60 Sekunden verlängern $lock->refresh(); } $lock->release();}
use Illuminate\Support\Facades\Cache;use Illuminate\Support\Facades\DB;public function index(): array{ $users = Cache::remember('all-users', 3600, function () { return DB::table('users')->orderBy('name')->get(); }); return compact('users');}
2
Cache invalidieren, wenn Daten aktualisiert werden
public function store(Request $request): RedirectResponse{ User::create($request->validated()); // Cache leeren, damit die Daten beim nächsten Zugriff neu geladen werden Cache::forget('all-users'); return redirect()->route('users.index');}