-
-
Notifications
You must be signed in to change notification settings - Fork 0
TTL and Expiry
Understand the two independent lifetimes in play — the per-key $ttl
argument and the ttl option — and the exact rules for null, zero, and
negative TTLs.
There are two TTLs, and they control different things:
Per-key $ttl argument |
ttl option |
|
|---|---|---|
| Set via |
set() / setArray() / push()
|
the constructor's options array |
| Controls | how long the manager treats an individual value as valid | how long the browser keeps the single transport cookie |
| Unit | seconds from now | seconds from now |
| Default |
null (lives as long as the transport cookie) |
2592000 (30 days) |
| Enforced by | the manager, lazily on read | the browser, via the cookie's Expires attribute |
use InitPHP\Cookies\Cookie;
// The browser keeps the transport cookie for 7 days...
$cookie = new Cookie('app_session', getenv('COOKIE_SALT'), [
'ttl' => 7 * 86400,
]);
// ...but this individual value is only valid for 1 hour.
$cookie->set('otp', '123456', 3600);The $ttl argument is a relative lifetime in seconds. Internally it is
converted to an absolute expiry timestamp at the moment you call set(), so
it counts from "now":
$cookie->set('token', 'abc', 3600); // valid for 1 hour
$cookie->has('token'); // true (right away)
$cookie->get('token'); // 'abc'push() and setArray() take the same $ttl:
$cookie->push('token', 'abc', 3600); // returns 'abc'
$cookie->setArray(['a' => '1', 'b' => '2'], 60); // both share a 60s TTLA null per-key TTL (the default) means the value lives as long as the
transport cookie. It never expires on its own:
$cookie->set('user_id', 42); // null TTL → no per-key expiry
$cookie->set('user_id', 42, null); // identicalExpiry is evaluated lazily, when you read. An expired entry is removed from the working copy as a side effect and reported as absent:
-
has()on an expired key removes it and returnsfalse. -
get()on an expired key removes it and returns the default. -
all()excludes (and removes) every expired entry.
// Suppose 'token' was set with a 1-second TTL two seconds ago.
$cookie->has('token'); // false — expired, now removed
$cookie->get('token', 'gone'); // 'gone'Because expired entries are stripped before re-encoding, they are never
re-sent: the next send() writes a cookie that no longer contains them. You
generally do not need to clean up expired values manually.
A $ttl of exactly 0 is rejected — a value that is valid for zero seconds
is meaningless. It throws
CookieInvalidArgumentException:
$cookie->set('k', 'v', 0); // throws CookieInvalidArgumentExceptionUse null for "no per-key expiry", or a positive integer for a real
lifetime.
A negative $ttl is not treated as "already expired". It is run through
abs(), so -100 behaves exactly like 100:
$cookie->set('k', 'v', -100); // abs(-100) → 100 seconds from now
$cookie->get('k'); // 'v' — still validThis is a deliberate normalization, so an accidental sign flip does not
silently drop a value. If you actually want to expire something, call
remove() instead of passing a negative TTL.
The browser deletes the whole transport cookie when its ttl option
elapses. Any per-key TTL longer than that cannot outlive it — the value is
gone with the cookie, regardless of what the manager thinks:
$cookie = new Cookie('app_session', $salt, ['ttl' => 3600]); // browser keeps it 1 hour
$cookie->set('remember', 'yes', 30 * 86400); // 30-day per-key TTL
// After 1 hour the browser drops the cookie. The 30-day TTL is silently lost.Keep per-key TTLs at or below the transport ttl for predictable behavior.
If you need a value to survive for 30 days, raise the transport ttl to at
least 30 days as well.
-
Confusing the two TTLs. Setting the
ttloption to60does not expire individual values after a minute — it sets the browser cookie lifetime. Per-value expiry is the$ttlargument ofset(). -
Passing
0to mean "no expiry". Zero throws. Usenull. -
Expecting a negative TTL to delete a value. It does the opposite
(normalized via
abs()). Useremove()to delete. -
Per-key TTL longer than the transport
ttl. The browser drops the whole cookie when the transport TTL elapses, so longer per-key TTLs cannot outlive it.
-
Configuration — the
ttloption and the rest of the cookie attributes. - Reading & Removing — how expired entries are dropped on read.
-
Basic Usage — the everyday
set/get/hasAPI.
initphp/cookies · MIT License · part of the InitPHP family
Source · Issues · Discussions · Packagist · Contributing · Security Policy
Getting Started
Core Usage
Reference
Practical Guides
Migration & Help