web php

Cookies

Cookies are small name/value pairs stored by the browser and sent back on later matching requests. PHP uses cookies for sessions, preferences, "remember me" identifiers, tracking consent, and other browser-specific state.

Cookies come from the client, so plain cookie values are not trusted facts. A user can edit or delete their own cookies.

Reading cookies

PHP example
<?php

declare(strict_types=1);

$_COOKIE['theme'] = 'dark';

$theme = in_array($_COOKIE['theme'] ?? 'light', ['light', 'dark'], true)
    ? $_COOKIE['theme']
    : 'light';

echo 'Theme: ' . $theme . PHP_EOL;

// Prints:
// Theme: dark

Allow-list cookie values. Do not put roles, prices, permissions, or user identity in unsigned plain cookies and treat them as truth.

Setting cookies

Use setcookie() before body output.

PHP example
<?php

declare(strict_types=1);

$cookieOptions = [
    'expires' => time() + 60 * 60 * 24 * 30,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
];

setcookie('theme', 'dark', $cookieOptions);

echo 'Cookie path: ' . $cookieOptions['path'] . PHP_EOL;

// Prints:
// Cookie path: /

The new cookie will be available to PHP on the next request, not immediately in $_COOKIE during the same request.

Deleting cookies

Delete a cookie by setting it with an expiry time in the past and the same path/domain options that were used to create it.

PHP example
<?php

declare(strict_types=1);

setcookie('theme', '', [
    'expires' => time() - 3600,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);

echo 'Delete cookie response prepared.' . PHP_EOL;

// Prints:
// Delete cookie response prepared.

Cookie deletion must match the original cookie's scope. If a cookie was set for a particular path or domain and the delete response uses different options, the original cookie may remain in the browser.

Browsers limit cookie size, and cookies are sent with matching HTTP requests. Do not store large JSON documents or whole user records in cookies. Large cookies add overhead to every request and are awkward to invalidate safely.

Use a cookie for a small preference or an opaque identifier. Store durable or trusted data on the server.

good fit: theme=dark
good fit: session=<opaque identifier>
bad fit:  role=admin
bad fit:  cart=<large product document>

Signed or encrypted cookies can protect integrity or confidentiality when a framework supports them, but they still need expiry rules and careful key management.

Two cookies can share a name while using different paths or domains. This can make debugging confusing because the browser decides which matching cookies to send.

Keep scope as narrow as the feature needs. Avoid setting domain unless subdomain sharing is intentional, and use the browser developer tools to inspect the exact cookies sent with a request.

What you should be able to do

After this lesson, you should be able to read cookies safely, set and delete cookies with matching scope, keep cookie values small, explain why cookies are not trusted storage, and remember that setcookie() changes a future browser request, not the current $_COOKIE array.

Practice

Task: Handle A Theme Cookie

Create a small PHP example for reading and setting a theme preference cookie.

Requirements

  • Allow only light and dark.
  • Fall back to light for missing or invalid values.
  • Show the setcookie() options you would use.
  • Include a delete-cookie example.
  • Add a short note explaining why a cookie value should not be trusted for permissions.

Check your work

The example should distinguish preference cookies from trusted server-side state.

Show solution
PHP example
<?php

declare(strict_types=1);

function normaliseTheme(string|null $value): string
{
    return in_array($value, ['light', 'dark'], true) ? $value : 'light';
}

$_COOKIE['theme'] = 'dark';

$theme = normaliseTheme($_COOKIE['theme'] ?? null);

setcookie('theme', $theme, [
    'expires' => time() + 60 * 60 * 24 * 365,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);

setcookie('theme', '', [
    'expires' => time() - 3600,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);

echo 'Theme: ' . $theme . PHP_EOL;

// Prints:
// Theme: dark

A theme cookie is a user preference, so it is safe to let the user change it within allowed values. Permissions are different: a user can edit their own cookies, so roles and authorization decisions must come from trusted server-side data.