dflydev/fig-cookies
PSR-7 cookie helper for managing Cookie request headers and Set-Cookie response headers. Provides Cookies and SetCookies collections to read from requests/responses, modify cookie values/attributes, and render updated headers back into PSR-7 messages.
Installation:
composer require dflydev/fig-cookies
First Use Case:
Reading a cookie from a PSR-7 Request:
use Dflydev\FigCookies\FigRequestCookies;
$cookie = FigRequestCookies::get($request, 'user_preference');
$value = $cookie->getValue(); // Returns 'dark' or null
Setting a cookie in a PSR-7 Response:
use Dflydev\FigCookies\FigResponseCookies;
use Dflydev\FigCookies\SetCookie;
$response = FigResponseCookies::set($response, SetCookie::create('theme', 'dark'));
FigRequestCookies and FigResponseCookies for simplicity.Cookie, Cookies, SetCookie, and SetCookies for granular control.Middleware for Cookie Handling:
use Dflydev\FigCookies\FigRequestCookies;
use Dflydev\FigCookies\FigResponseCookies;
public function handle($request, Closure $next) {
// Read a cookie
$theme = FigRequestCookies::get($request, 'theme')->getValue();
// Modify request (e.g., attach theme to request)
$request = $request->withAttribute('theme', $theme);
// Process request
$response = $next($request);
// Set a cookie based on response logic
if ($theme === 'dark') {
$response = FigResponseCookies::set($response, SetCookie::create('theme', 'dark')->rememberForever());
}
return $response;
}
Service Layer for Cookie Operations:
class CookieService {
public function getUserPreference(Request $request): ?string {
return FigRequestCookies::get($request, 'user_preference')->getValue();
}
public function setUserPreference(Response $response, string $preference): Response {
return FigResponseCookies::set($response, SetCookie::create('user_preference', $preference)->rememberForever());
}
}
Bulk Cookie Operations:
// Read all cookies (primitive approach)
$cookies = Cookies::fromRequest($request);
foreach ($cookies as $cookie) {
// Process each cookie
}
// Set multiple cookies
$setCookies = SetCookies::create();
$setCookies = $setCookies->with(SetCookie::create('cookie1', 'value1'));
$setCookies = $setCookies->with(SetCookie::create('cookie2', 'value2'));
$response = $setCookies->renderIntoSetCookieHeader($response);
FigRequestCookies/FigResponseCookies in middleware to read/write cookies without mutating the request/response directly.Illuminate\Http\Request and Illuminate\Http\Response by casting to PSR-7 interfaces:
$psr7Request = new Zend\Diactoros\ServerRequest($request->createFromBase());
$cookie = FigRequestCookies::get($psr7Request, 'key')->getValue();
Symfony\Component\HttpFoundation\Request/Response with PSR-7 adapters like nyholm/psr7.$request = FigRequestCookies::set(...)).Performance Overhead:
FigRequestCookies, FigResponseCookies) create new Cookies/SetCookies instances and rebuild headers on every call. Avoid chaining multiple facade calls in tight loops.Cookies, SetCookies) for batch operations.Strict Types:
declare(strict_types=1) and update type hints (e.g., ?string for nullable values).// Old (pre-2.0)
$cookie = Cookie::create('name', null);
// New (2.0+)
$cookie = Cookie::create('name', null); // Valid, but ensure callers handle null
Cookie Expiry:
SetCookie with the same domain/path as the original. Forgetting this causes the client to ignore the expiry.SetCookie configurations or recreate them identically.PSR-7 Compatibility:
$_COOKIE into headers. Test with your HTTP server (e.g., Swoole, ReactPHP) to ensure cookies are correctly parsed.$_COOKIE (e.g., zend-diactoros with PHP's built-in server).Facade vs. Primitive Tradeoffs:
// Facade (simple)
$request = FigRequestCookies::set($request, Cookie::create('key', 'value'));
// Primitive (batch)
$cookies = Cookies::fromRequest($request);
$cookies = $cookies->with(Cookie::create('key1', 'value1'));
$cookies = $cookies->with(Cookie::create('key2', 'value2'));
$request = $cookies->renderIntoCookieHeader($request);
Inspect Headers:
dump($request->getHeader('Cookie')); // For request cookies
dump($response->getHeader('Set-Cookie')); // For response cookies
Cookie String Parsing:
Cookie::listFromCookieString() to debug malformed cookie strings:
$cookies = Cookie::listFromCookieString($request->getHeaderLine('Cookie'));
SameSite Attributes:
SameSite modifiers are set correctly (e.g., SameSite::lax()). Browsers enforce these strictly.$setCookie = SetCookie::create('session')
->withValue('abc123')
->withSameSite(SameSite::lax());
Custom Cookie Attributes:
SetCookie to support non-standard attributes (e.g., Priority):
class ExtendedSetCookie extends SetCookie {
public function withPriority(string $priority): self {
return $this->withAttribute('Priority', $priority);
}
}
Cookie Validation:
$validator = function (Cookie $cookie) {
if (!preg_match('/^[a-z]+$/', $cookie->getValue())) {
throw new \InvalidArgumentException('Invalid cookie value');
}
return $cookie;
};
$request = FigRequestCookies::modify($request, 'theme', $validator);
PSR-15 Middleware:
class CookieMiddleware implements MiddlewareInterface {
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
$request = FigRequestCookies::set($request, Cookie::create('visited', 'true'));
return $handler->handle($request);
}
}
Cookie Serialization:
$cookies = Cookies::fromRequest($request);
$serialized = json_encode(array_map(fn($c) => [$c->getName() => $c->getValue()], $cookies->all()));
How can I help you explore Laravel packages today?