Caching in PHP is een van de meest effectieve manieren om je applicatie sneller te maken zonder dure hardware-upgrades. Door resultaten van zware berekeningen, databasequeries of API-calls tijdelijk op te slaan, voorkom je dat je server telkens hetzelfde werk opnieuw doet.
In deze gids leer je welke cachetechnieken PHP biedt, wanneer je ze inzet en hoe je ze praktisch toepast. Van opcache tot Redis en HTTP caching, je krijgt alle lagen helder uitgelegd.
Deze gids bouwt voort op onze eerdere uitleg over PHP performance optimalisatie. Waar dat artikel breed ingaat op performance, duiken we hier specifiek in caching.
Wat is caching en waarom werkt het?
Caching draait om één principe: werk dat je al een keer hebt gedaan, hoef je niet opnieuw te doen. In plaats van een database te bevragen of een bestand te parsen, haal je het resultaat uit een snelle opslaglocatie, meestal RAM.
De winst is enorm. Een databasequery kan tientallen milliseconden duren, terwijl een cache lookup vaak minder dan een milliseconde kost. Voor pagina's met veel dynamische data maakt dat het verschil tussen een trage en een razendsnelle ervaring.
Caching bestaat uit verschillende lagen. Je hebt caching op codeniveau (opcache), op applicatieniveau (object cache), op databaseniveau (query cache) en op netwerkniveau (HTTP caching). Elke laag heeft zijn eigen rol.
Opcache: de basis van PHP performance
Elke keer dat PHP een script uitvoert, wordt de code geparsed en gecompileerd naar bytecode. Zonder caching gebeurt dit bij elke request opnieuw, puur weggegooid werk.
Opcache lost dit op door de gecompileerde bytecode in het geheugen te bewaren. Bij volgende requests slaat PHP de parse- en compilatiestap over en voert direct de bytecode uit.
Opcache configureren
Opcache zit standaard in PHP vanaf versie 5.5. Je activeert en tuned hem in php.ini:
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
In productie zet je validate_timestamps=0 voor maximale performance. PHP controleert dan niet langer of bestanden zijn gewijzigd, je moet opcache handmatig resetten bij deploys.
Meer configuratieopties vind je in de officiële PHP opcache documentatie.
Preloading voor nog meer snelheid
Sinds PHP 7.4 kun je met preloading een set bestanden al bij het opstarten van PHP-FPM laden. Dat scheelt opnieuw tijd bij elke request. Vooral frameworks zoals Laravel profiteren hiervan.
Object caching met APCu
Waar opcache je code versnelt, versnelt APCu je applicatiedata. APCu (Alternative PHP Cache, User) is een in-memory key-value store die alleen binnen één PHP-proces beschikbaar is.
// Waarde opslaan met TTL van 300 seconden
apcu_store('gebruikers_lijst', $gebruikers, 300);
// Ophalen met fallback
$gebruikers = apcu_fetch('gebruikers_lijst', $success);
if (!$success) {
$gebruikers = haalGebruikersOpUitDatabase();
apcu_store('gebruikers_lijst', $gebruikers, 300);
}
APCu is ideaal voor single-server setups waar je geen externe dependency wilt. Het is snel, simpel en vereist geen extra infrastructuur.
Nadeel: APCu werkt niet over meerdere servers. Heb je een loadbalancer? Dan heeft elke server zijn eigen cache en kun je inconsistenties krijgen.
Redis en Memcached voor gedistribueerde caching
Zodra je meer dan één webserver draait, heb je een centrale cache nodig. Redis en Memcached zijn de twee populairste opties.
Redis gebruiken in PHP
Redis is een volwaardige datastore die meer kan dan caching alleen: lists, sets, sorted sets, pub/sub en persistence. Voor PHP gebruik je de phpredis extensie of de Predis library via Composer.
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = 'product:123';
$product = $redis->get($key);
if ($product === false) {
$product = haalProductOp(123);
$redis->setex($key, 600, serialize($product));
} else {
$product = unserialize($product);
}
De setex methode combineert set en expire in één call, handig om vergeten TTL's te voorkomen.
Memcached als alternatief
Memcached is simpeler: puur een key-value cache zonder persistence of geavanceerde datastructuren. Voor pure caching is het iets sneller dan Redis, maar de flexibiliteit van Redis maakt het meestal de betere keuze.
Caching van databasequeries
Databases zijn vaak de grootste bottleneck in een PHP-applicatie. Door queryresultaten te cachen, haal je enorme winst.
In onze gids over werken met databases via PDO zie je hoe je queries uitvoert. Het cachen daarvan kun je als volgt doen:
function haalActieveGebruikers(PDO $pdo, Redis $redis): array
{
$cacheKey = 'gebruikers:actief';
$cached = $redis->get($cacheKey);
if ($cached !== false) {
return unserialize($cached);
}
$stmt = $pdo->query('SELECT id, naam FROM gebruikers WHERE actief = 1');
$gebruikers = $stmt->fetchAll(PDO::FETCH_ASSOC);
$redis->setex($cacheKey, 300, serialize($gebruikers));
return $gebruikers;
}
Deze pattern, read-through caching, werkt voor bijna elke databaseoperatie. Bij writes invalideer je de bijbehorende cache keys.
HTTP caching met headers
Niet alle caching gebeurt server-side. HTTP caching laat browsers en proxies responses hergebruiken zonder je server te raken.
$etag = md5_file('data.json');
header('ETag: "' . $etag . '"');
header('Cache-Control: public, max-age=3600');
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') === $etag) {
http_response_code(304);
exit;
}
readfile('data.json');
Met ETag en Cache-Control vertel je de browser hoelang hij een response mag hergebruiken. Een 304-response kost bijna niks en scheelt volledige data-transfers.
Voor API's die je zelf bouwt, zie onze API handleiding, is HTTP caching essentieel voor schaalbaarheid.
Cache-invalidatie: het moeilijkste probleem
"There are only two hard things in Computer Science: cache invalidation and naming things." Die quote is niet voor niets beroemd.
Verouderde data serveren is erger dan geen cache hebben. Een paar strategieën helpen:
- Time-based expiry (TTL): eenvoudig maar grof. Je accepteert een bepaalde stale-tijd.
- Explicit invalidation: je verwijdert cache keys zodra onderliggende data verandert.
- Cache tags: je groepeert keys onder een tag en invalideert de hele groep in één keer.
- Versioned keys: je neemt een versienummer op in de key en verhoogt het bij wijzigingen.
Kies de strategie die past bij hoe vaak je data wijzigt en hoeveel staleness acceptabel is.
Wanneer cachen, en wanneer niet
Caching is geen silver bullet. Voor deze gevallen werkt het uitstekend:
- Dure databasequeries die vaak voorkomen
- Externe API-responses met stabiele data
- Zware berekeningen of rapportages
- Rendering van pagina's met veel dynamische blokken
Voor deze gevallen is caching risicovol of overbodig:
- Persoonlijke data per gebruiker (tenzij per-user gecached)
- Data die per seconde wijzigt (bijvoorbeeld realtime prijzen)
- Simpele queries die al binnen 1ms draaien
- Debug- of admin-pagina's waar staleness verwarring geeft
Meet eerst met profiling tools zoals Blackfire of Tideways waar je bottleneck zit. Cachen waar het niet nodig is, voegt alleen complexiteit toe.
Caching in frameworks
Moderne frameworks regelen caching grotendeels voor je. In Laravel heb je de Cache facade die met één API werkt op Redis, Memcached, APCu of file-based storage:
$gebruikers = Cache::remember('gebruikers:actief', 300, function () {
return Gebruiker::where('actief', true)->get();
});
Deze remember methode combineert check, fetch en store in één regel. Symfony, CodeIgniter en andere frameworks hebben vergelijkbare abstracties.
Een goede externe resource om dieper in caching strategieën te duiken is de PSR-6 en PSR-16 cache standaarden van de PHP-FIG.
Veelgestelde vragen
Wat is caching in PHP?
Caching in PHP is het tijdelijk opslaan van data of gecompileerde code zodat je die niet telkens opnieuw hoeft te berekenen of op te halen. Het resultaat is een fors snellere applicatie met minder belasting op je server en database.
Wat is het verschil tussen opcache en object cache?
Opcache slaat gecompileerde PHP-bytecode op in het geheugen zodat scripts niet opnieuw geparsed worden. Object cache slaat applicatiedata op, zoals databaseresultaten of API-responses, zodat je die niet opnieuw hoeft op te halen.
Wanneer gebruik je Redis of Memcached?
Je gebruikt Redis of Memcached wanneer je cache gedeeld moet worden tussen meerdere servers of processen. Voor single-server setups kan APCu voldoende zijn, maar Redis biedt meer features zoals persistence en datastructuren.
Hoe voorkom je verouderde cache data?
Gebruik een goede cache-invalidatiestrategie: zet een TTL (time-to-live) op elke cache entry en invalideer expliciet wanneer onderliggende data wijzigt. Cache-tags en versie-keys helpen om gerelateerde data in één keer ongeldig te maken.
Is caching altijd een goed idee?
Nee, caching voegt complexiteit toe en kan bugs veroorzaken bij verkeerde invalidatie. Voor data die vaak wijzigt of persoonlijk is, levert caching soms meer problemen op dan winst. Meet eerst of caching daadwerkelijk een bottleneck oplost.
Conclusie
Caching is een van de krachtigste tools in je PHP-toolbox. Met opcache versnel je je code, met APCu of Redis je applicatiedata, en met HTTP headers je volledige responses. Gecombineerd maken ze het verschil tussen een trage en een razendsnelle applicatie.
Begin eenvoudig: activeer opcache, cache je duurste queries en meet het effect. Schaal vervolgens op naar Redis zodra je meerdere servers draait. En onthoud: cache-invalidatie is het moeilijkste onderdeel, investeer daar net zoveel aandacht in als in het cachen zelf.