Skip to content

[13.x] Make Cache touch() TTL required and remove redundant value fetching #59121

Merged
taylorotwell merged 1 commit intolaravel:13.xfrom
SanderMuller:suggestion/cache-touch-api
Mar 10, 2026
Merged

[13.x] Make Cache touch() TTL required and remove redundant value fetching #59121
taylorotwell merged 1 commit intolaravel:13.xfrom
SanderMuller:suggestion/cache-touch-api

Conversation

@SanderMuller
Copy link
Copy Markdown
Contributor

This PR makes two changes to Cache::touch() before the 13.x API surface is finalized:

1. Make $ttl a required parameter

Currently, Cache::touch($key) with no TTL silently converts the item to live forever via $this->forever().
This is surprising behavior for a method whose purpose is TTL extension. A developer calling Cache::touch('session-key') to "bump" an expiration would not expect to accidentally make the item permanent.

Unlike put(), where null TTL meaning "forever" is a convenience shorthand with a clear value being stored, touch() is specifically about managing expiration. Having it silently remove expiration contradicts its purpose.

Making $ttl required forces explicit intent: developers who want an item to live forever should call Cache::forever() directly.

2. Remove the redundant $this->get() call from the Repository layer

The current implementation fetches the full cached value at the Repository level before delegating to the store:

public function touch($key, $ttl = null)
{
    $value = $this->get($key);          // ← fetches full value
    if (is_null($value)) return false;
    // ...
    $this->store->touch($key, $seconds); // ← store doesn't need the value
}

This is unnecessary because every store implementation already handles the "key doesn't exist" case by returning false:

  • Redis — EXPIRE returns 0 for nonexistent keys
  • Database — UPDATE ... WHERE expiration > now affects 0 rows
  • DynamoDB — ConditionalCheckFailedException caught and returns false
  • Memcached — native touch() returns false
  • File/APC — fetch the value internally and return false if missing

For the four atomic stores (Redis, Database, DynamoDB, Memcached), the Repository-level get() is pure overhead, it deserializes the entire cached value only to throw it away. For File and APC stores, the value ends up being fetched twice: once at the Repository layer and once inside the store.

After this change, the Repository simply converts the TTL and delegates:

public function touch($key, $ttl)
{
    return $this->store->touch($this->itemKey($key), $this->getSeconds($ttl));
}

Change before the new cache touch API goes live

This is a breaking change to a new cache API introduced in 13.x, so there is no backward-compatibility concern with 11.x or 12.x users. The method signature changes from touch($key, $ttl = null) to touch($key, $ttl).

@taylorotwell taylorotwell merged commit 9f456f6 into laravel:13.x Mar 10, 2026
54 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants