Although PHP unsets all the variables after processing the request, we often need to persist the data to use it in the future. For example, an e-commerce site must save the data about products it sells, the cart states, and orders users make.

This chapter covers data storage mechanisms that don’t involve database engines. Let’s start with caching. It’s not a long-term persistence mechanism, but it manages to save the data between requests.

What’s caching?

Caching means saving some of our results so we don’t have to recalculate them again. Imagine we have a long-running task—finding prime factors of a big number. If we need to use the results multiple times, we save the calculation result (cache it) to avoid repeating expensive calculations. A task doesn’t have to be computation-intensive to make us cache it. Imagine we’re getting a news feed from an external service that will be displayed on our page. Calls to external services are slow. Also, providers might not like it if we call them too often. That’s why we cache news feeds and serve them from the cache later.

Cache invalidation

The famous joke states that computer science has only two hard problems—cache invalidation and naming things. Cache invalidation is indeed challenging.

In the previous example, we retrieve the news feed from an external service, cache it, and serve it from the cache later. How do we know when we should update the cached values? Usually, we don’t. Here are some ways to work with that.

Cache invalidation via TTL

The most common method is assigning time-to-live (TTL) to cache records. After this time passes, we have to update the data.

Picking a good TTL value is tricky, though. If we set it too big, we might serve stale data for a long time. If we set it too small, we might update data too often just to see that it didn’t change. It’s like checking the fridge every five minutes in case something interesting has magically appeared there.

Most cache storages support TTL and delete stale records automatically. Even if we rely on other cache invalidation methods, setting TTL for records is still valid. It prevents the cache storage from keeping abandoned records forever.

Cache invalidation via tag

Another way to check to see if the cache is stale is to find an easy-to-get property that signifies that data has changed. For example, imagine a store inventory system. We need to retrieve all the products from the database and render a price list in the form of a PDF file. It’s slow, but we can cache the file and reuse it if products remain unchanged. We tag the cache record by adding the modification time of the last-modified product. Later we can get the latest product modification time from the database and use the cached file if it matches the cache tag.

Querying a database to get the latest product modification time is much faster than rendering a new file, and with such a technique, we’ll never serve the file with outdated contents.

Explicit cache invalidation

Cache invalidation problems disappear when we switch from pulling changes to pushing them.

Let’s get back to the price list file example. What if we could explicitly delete the cached file every time the product changes? We wouldn’t have to bother with cache invalidation at all!

Unfortunately, often it’s not possible—either we don’t have the change event, like in the external news feed example, or we can’t control every cache storage.

Another issue occurs when we must invalidate so many cache records on every change that it becomes slow.

Caching in PHP with APCu

The primary caching mechanism for PHP is APCu. It’s a PHP extension, so we can use it without running separate servers or daemons.

Here’s how we can use it:

Get hands-on with 1200+ tech skills courses.