activecollab/cookies
A thin PSR-7 cookie library built on top of dflydev/fig-cookies. It adds automatic name prefixing, optional value encryption, URL-based configuration, and secure defaults so you can work with cookies without worrying about the low-level header plumbing.
Installation
composer require activecollab/cookies
Quick Start
use ActiveCollab\Cookies\Cookies;
$cookies = new Cookies();
$value = $cookies->get($request, 'session_id');
[$request, $response] = $cookies->set($request, $response, 'session_id', 'abc123');
[$request, $response] = $cookies->remove($request, $response, 'session_id');
Every method accepts and returns standard PSR-7 message objects (ServerRequestInterface, ResponseInterface), so the library slots into any middleware stack.
How It Works
The library revolves around a single entry point, the Cookies class (implementing CookiesInterface). It is responsible for three operations:
Getting a cookie reads the Cookie header from the incoming request and returns the value for the given name (after optional decryption and prefix resolution).
Setting a cookie applies the value to both the request object (so downstream middleware can see it immediately) and the response object (by adding a Set-Cookie header with all configured attributes like domain, path, expiry, security flags, etc.).
Removing a cookie works like setting operation, but with an empty value and an expiry date in the past, so the browser discards it.
Configuration
All configuration is done through a fluent interface on the Cookies instance. Every setter returns $this, so calls can be chained.
Settings Overview
| Domain | getDomain() | domain(string) | '' (empty) | Cookie domain attribute. |
| Path | getPath() | path(string) | '/' | Cookie path attribute. |
| Secure | getSecure() | secure(bool) | true | Send cookie only over HTTPS. |
| HttpOnly | getHttpOnly() | httpOnly(bool) | true | Hide cookie from JavaScript. |
| SameSite | getSameSite() | sameSite(SameSite) | Lax | Cross-site request policy. |
| Default TTL | getDefaultTtl() | defaultTtl(int) | 1209600 (14 days) | Time-to-live in seconds. |
| Prefix | getPrefix() | prefix(string) | '' (empty) | String prepended to every cookie name. |
| Encryptor | getEncryptor() | encryptor(EncryptorInterface) | null | Encrypt/decrypt cookie values. |
Secure, HttpOnly, and the SameSite
The library ships with modern security defaults out of the box:
$cookies = new Cookies();
$cookies->getSecure();
$cookies->getHttpOnly();
$cookies->getSameSite();
Override any of them when the use case requires it:
use Dflydev\FigCookies\Modifier\SameSite;
$cookies->httpOnly(false);
$cookies->sameSite(SameSite::none());
$cookies->secure(true);
$cookies->sameSite(SameSite::strict());
Per-Cookie Settings
The set() method accepts an optional $settings array as its fifth argument. These options override global defaults for that single cookie only:
[$request, $response] = $cookies->set(
$request,
$response,
'name',
'value',
$settings,
);
ttl | int | Value of getDefaultTtl() (14 days) | Time-to-live in seconds. The cookie's Expires attribute is computed as current timestamp plus this value. |
http_only | bool | Value of getHttpOnly() (true) | Whether the cookie should be hidden from JavaScript. Set to false for cookies that client-side code needs to read. |
same_site | SameSite | Value of getSameSite() (Lax) | Cross-site request policy for this cookie. Accepts SameSite::lax(), SameSite::strict(), or SameSite::none(). |
encrypt | bool | true | Whether to encrypt the value before writing. Only relevant when an encryptor is configured. Set to false to store the value in plain text. |
All other cookie attributes (domain, path, and secure) are always taken from the global Cookies configuration and cannot be overridden per cookie.
Example — a short-lived, JS-accessible, unencrypted preference cookie:
[$request, $response] = $cookies->set(
$request,
$response,
'theme',
'dark',
[
'ttl' => 31536000, // 1 year
'http_only' => false, // readable by document.cookie
'encrypt' => false, // store as plain text
],
);
Example — a CSRF token cookie with a stricter same-site policy than the global default:
use Dflydev\FigCookies\Modifier\SameSite;
[$request, $response] = $cookies->set(
$request,
$response,
'csrf_token',
$token,
['same_site' => SameSite::strict()],
);
Configure From URL
The most convenient way to configure domain, path, secure, and prefix all at once is from your application's URL:
$cookies->configureFromUrl('https://app.example.com/projects');
$cookies->getDomain();
$cookies->getPath();
$cookies->getSecure();
$cookies->getPrefix();
An http:// URL will set secure to false. The prefix is only auto-generated when one has not already been set, so calling prefix() before configureFromUrl() preserves your choice.
Cookie Name Prefixing
Prefixing avoids collisions when multiple applications share the same domain:
$cookies = (new Cookies())->prefix('myapp_');
[$request, $response] = $cookies->set($request, $response, 'session_id', 'abc');
$value = $cookies->get($request, 'session_id');
Encryption
When an encryptor is provided, cookie values are automatically encrypted on set() and decrypted on get(). The encryptor must implement ActiveCollab\Encryptor\EncryptorInterface from the activecollab/utils package.
use ActiveCollab\Encryptor\Encryptor;
$cookies = (new Cookies())->encryptor(
new Encryptor('your-32-character-secret-key-here'),
);
[$request, $response] = $cookies->set($request, $response, 'token', 'sensitive-value');
$cookies->get($request, 'token');
To skip encryption for a specific cookie, pass 'encrypt' => false in settings:
[$request, $response] = $cookies->set(
$request,
$response,
'public_pref',
'dark-mode',
['encrypt' => false],
);
$cookies->get($request, 'public_pref', null, decrypt: false);
TTL and Expiry
The default time-to-live is 14 days. Change it globally or per cookie:
$cookies->defaultTtl(3600);
[$request, $response] = $cookies->set(
$request,
$response,
'short_lived',
'value',
['ttl' => 1800],
);