A PHP cookie is a small key-value string stored in the user's browser and sent back to your server automatically on matching requests via $_COOKIE. Cookies work well for UI preferences such as dark mode, language selection, or opaque session identifiers—never for storing sensitive data like passwords or user roles directly.
Because HTTP cookies travel inside response headers, you must call setcookie() before sending any HTML or whitespace output to the browser. Always pass the modern options array to enable httponly, secure, and samesite protections.
<?php
declare(strict_types=1);
// Must execute before any HTML output
setcookie('ui_theme', 'dark', [
'expires' => time() + (86400 * 30), // 30 days
'path' => '/',
'secure' => true, // Send only over HTTPS
'httponly' => true, // Block JavaScript document.cookie access
'samesite' => 'Lax', // Protect against CSRF
]);
$activeTheme = $_COOKIE['ui_theme'] ?? 'light';
echo "Preferred theme: " . htmlspecialchars($activeTheme, ENT_QUOTES, 'UTF-8') . PHP_EOL;
Keep in mind that setcookie() sends a Set-Cookie header in the response; $_COOKIE only reflects cookies sent by the browser in the current request. To delete a cookie, call setcookie() again with the same path and an expires timestamp in the past (for example, time() - 3600).
setcookie() after echo or HTML: Sending body output first triggers a "Cannot modify header information - headers already sent" error.httponly on authentication cookies: Without httponly => true, any XSS vulnerability lets malicious JavaScript steal the cookie via document.cookie.is_admin=1 in a cookie lets any visitor edit the value in DevTools and gain admin access. Store authorization state on the server using sessions or signed tokens.Most browsers limit each cookie to roughly 4,096 bytes (4 KB) including name, value, and attributes. Store larger payloads on the server instead.
$_COOKIE['ui_theme'] empty right after calling setcookie()?$_COOKIE contains values sent by the browser when the request arrived. The new cookie becomes readable in $_COOKIE on the next HTTP request.
samesite => 'Lax' do?SameSite=Lax allows the cookie on normal top-level navigation links into your site while blocking it on cross-site POST requests, preventing common CSRF attacks.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.