タイトル: $_COOKIE
SEOタイトル: PHP $_COOKIE スーパーグローバル変数完全ガイド(setcookie / Secure / HttpOnly / SameSite)
| この記事の要点 |
|
$_COOKIE とは
$_COOKIE は PHP のスーパーグローバル変数の一つで、HTTP リクエストヘッダの Cookie: でクライアントから送られてきた値が、名前 => 値の連想配列として格納されています。

string(26) "abc123..."
// ["lang"]=> string(2) "ja"
// }
// 個別取得
$lang = $_COOKIE['lang'] ?? 'en';
// 存在チェック
if (isset($_COOKIE['user_id'])) {
echo "ようこそ ID:" . htmlspecialchars($_COOKIE['user_id']);
}
注意点として、$_COOKIE はクライアントが提示した値であり、ユーザーが書き換え可能です。サーバ側ロジックの認可判定に使う場合、必ず署名 / Session ID / トークンで改ざん検知を行ってください。
setcookie() で Cookie を書き込む

PHP 7.3 以降では連想配列で指定する形式が推奨されています:
time() + 3600, // 1時間後
'path' => '/',
'domain' => 'example.com',
'secure' => true, // HTTPS のみ送信
'httponly' => true, // JavaScript 不可
'samesite' => 'Lax', // CSRF 対策 (Lax / Strict / None)
]);
// 旧形式(PHP 7.2 以前との互換)
setcookie('lang', 'ja', time() + 86400, '/', '', true, true);
// ↑ ↑ ↑ ↑ ↑ ↑ ↑
// value expires path domain secure httponly
setcookie() はHTTP ヘッダで送出するため、必ず echo や HTML 出力より前に呼び出します。出力後に呼ぶと Cannot modify header information - headers already sent エラーになります。
セキュリティ属性: Secure / HttpOnly / SameSite
| 属性 | 効果 | 推奨 |
|---|---|---|
| Secure | HTTPS 接続でのみ Cookie を送信 | 常に true(HTTPS 環境前提) |
| HttpOnly | JavaScript (document.cookie) から不可視 | セッション系は必ず true(XSS 軽減) |
| SameSite=Strict | 同サイト発リクエストのみ送信 | 強固。OAuth リダイレクトで切れる |
| SameSite=Lax | 同サイト + トップレベルナビゲーション GET | ★ 既定の現実解 |
| SameSite=None | クロスサイト送信を許可(要 Secure) | 埋め込み iframe など限定 |

Cookie の削除
Cookie 専用の削除 API はありません。有効期限を過去に設定した同名 Cookie を送ると、ブラウザが削除します。
time() - 3600, // 過去
'path' => '/',
'domain' => 'example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
// 削除時の path / domain は 設定時と同じでないと削除されない
// 設定: path=/admin で書いた Cookie は path=/admin で削除する
Cookie 読み取りの実例

time() + 86400 * 30,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
// 認証トークンの検証(HMAC 署名例)
$token = $_COOKIE['auth'] ?? '';
[$payload, $sig] = explode('.', $token, 2) + ['', ''];
$expect = hash_hmac('sha256', $payload, $secretKey);
if (hash_equals($expect, $sig)) {
// 改ざんなし
$user = json_decode(base64_decode($payload), true);
}
Cookie の制限
| 項目 | 制限 |
|---|---|
| 1 Cookie のサイズ | 約 4KB(4096 バイト) |
| 1 ドメインあたりの Cookie 数 | 約 50 個(ブラウザ依存、Chrome は約 180) |
| 1 ドメインの Cookie 合計サイズ | 約 4KB × 個数 |
| 名前に使える文字 | RFC 6265 トークン、= , ; 不可 |
| 値に使える文字 | 制御文字 / , ; " 不可(PHP は自動で URL エンコード) |
Cookie vs Session の使い分け
| 用途 | Cookie | Session |
|---|---|---|
| 言語・テーマ設定 | ★ | — |
| 同意バナー記録 | ★ | — |
| ログイン状態 | セッション ID のみ | ★(ユーザー情報本体) |
| カート内容 | 軽量なら可 | ★ 重い場合 |
| パスワード / トークン秘密 | × | ★ |
セッションハイジャック対策
- HTTPS 強制(HSTS)+
Secure属性 HttpOnlyで XSS 経由の盗難を防ぐSameSite=Lax以上で CSRF を緩和- ログイン直後に
session_regenerate_id(true)でセッション固定攻撃防止 - 長時間使うトークンは定期ローテーション(refresh token 方式)
- 機密 Cookie は __Host- プレフィックス(Secure + path=/ + domain なし強制)
Content Security Policy (CSP) との連携
# レスポンスヘッダ
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
CSP で XSS の発生確率を下げ、HttpOnly Cookie の漏洩リスクを併せて低減できます。
Laravel の Cookie ファサード
use Illuminate\Support\Facades\Cookie;
// 書き込み(暗号化 + 署名済み)
return response('OK')->cookie(
'lang', 'ja', 60, '/', null, true, true, false, 'Lax'
);
// 読み取り
$lang = request()->cookie('lang', 'en');
// 削除
return response('OK')->withCookie(Cookie::forget('lang'));
// 暗号化を除外(フロント JS で読みたい場合)
// app/Http/Middleware/EncryptCookies.php
protected $except = ['lang'];
Laravel は既定でCookie を AES 暗号化するため、生 PHP の $_COOKIE から直接読むと暗号文が返ります。フロント側で読みたい Cookie は EncryptCookies の除外リストに入れます。
FAQ
Q: setcookie() したのに $_COOKIE に出ない
A: $_COOKIE は次のリクエストから反映されます。同じリクエスト内で参照したい場合は $_COOKIE['x'] = 'v' も手で設定するか、setcookie() 直後にローカル変数で持ちます。
Q: ヘッダ送信済みエラーが出る
A: ファイル先頭の BOM / 余計な空白、もしくは echo 後に setcookie() を呼んでいます。ob_start() でバッファリングするか、出力前に呼びましょう。
Q: SameSite=None にしたら Cookie が送られなくなった
A: モダンブラウザは SameSite=None 時に Secure を要求します。HTTPS 環境で Secure=true を併用してください。