ch03 6章中 3章目

ch03 — `setcookie()` と `$_COOKIE`

スライドで見る

この章を AI と学ぶ

💬 AI に聞く質問例 3 件
  1. 「ch03 — `setcookie()` と `$_COOKIE`」のつまずきやすいポイントを、初学者向けに3つ教えてください

    ChatGPT Claude Gemini

  2. 「ch03 — `setcookie()` と `$_COOKIE`」について、自分の手で試せる練習問題を3つ出してください (難易度を上げながら)

    ChatGPT Claude Gemini

  3. 「ch03 — `setcookie()` と `$_COOKIE`」を学んだ後、次に学ぶと良いトピックは何ですか?理由も教えてください

    ChatGPT Claude Gemini

概要

Session の裏側で使われている Cookie 自体を 直接 扱う章。書き込みは setcookie('name', 'value')、読み込みは $_COOKIE['name']。Session を立てるほどでもない軽い情報 (ダークモード設定・言語選択など) を保つ用途で実務でも頻出する。

setcookie() は多くのオプションを取る。第 3 引数で 有効期限 (UNIX タイムスタンプ)、配列形式で渡せば Path / Domain / Secure / HttpOnly を細かく指定できる。とくに HttpOnly (JavaScript から読めない) と Secure (HTTPS 専用) は XSS や盗聴対策の必須属性で、Session Cookie には絶対に付けたい。

setcookie() で書いた値は 「ブラウザに『次から送ってね』と頼んでいるだけ」 で、自分の $_COOKIE には即時反映されない。$_COOKIE に乗ってくるのは 次のリクエスト から。これも HTTP が 1 往復で完結することの帰結。CLI 採点ランナーでは、stdin から Cookie 文字列を読んで $_COOKIE を手で組み立てるスタブで疑似化する。

学習目標

  • setcookie('name', 'value') でブラウザに Cookie を書き出せる
  • $_COOKIE['name'] でブラウザから送られてきた Cookie を読める
  • 採点用に stdin から Cookie 文字列を読んで $_COOKIE をスタブする 書き方を知る

ドリル

no 内容
01 stdin から name=太郎 を読み、$_COOKIE['name'] を出力
02 stdin の複数行から key=value を読み、$_COOKIE を組み立てて出力

本物の Cookie 動作で確認したい場合

cd topics/session-cookie/ch03-cookie-basic/drill/01-read-cookie/
php -S localhost:8000 answer.php

ブラウザの開発者ツール (Application → Cookies) で Cookie を手動で追加し、リロードして $_COOKIE 経由で読めることを確認する。

解説スライド 全 7 枚

右の ボタン キー(またはスワイプ)で次のスライドに進めます。 下の「縦表示」を開くと全スライドを一気に読めます。

  1. setcookie()$_COOKIE

    Lesson 13 / Chapter 3

  2. Cookie のやり取り (絵)

    1. ブラウザがリクエスト
       GET / HTTP/1.1
    
    2. サーバーがレスポンスに Set-Cookie ヘッダを乗せる
       HTTP/1.1 200 OK
       Set-Cookie: name=taro
    
    3. ブラウザが Cookie を保存する
    
    4. 次回以降のリクエストに自動で乗せて送る
       GET /page HTTP/1.1
       Cookie: name=taro

    PHP からは:

    • 書き出す: setcookie('name', 'taro')
    • 読む: $_COOKIE['name'] (連想配列)
  3. 最小のサンプル

    <?php
    // 1. ブラウザに Cookie を書く (echo より前で呼ぶ)
    setcookie('name', '太郎');
    
    // 2. 次回以降、ブラウザが送ってきた Cookie を読む
    $name = $_COOKIE['name'] ?? 'guest';
    echo "こんにちは、{$name}さん\n";
    • setcookie()echo の前 で呼ぶ (HTTP ヘッダは本文より前に送る必要がある)
    • 初回アクセス時は $_COOKIE は空 → ??guest にフォールバック
    • リロードすると Cookie が乗ってきて 太郎 が出る
  4. setcookie() のオプション (重要 3 つ)

    setcookie(
        'name',           // key
        '太郎',           // value
        [
            'expires'  => time() + 3600,   // 1 時間後に消える
            'httponly' => true,            // JS から読めない (XSS 対策)
            'samesite' => 'Lax',           // CSRF 対策
            'secure'   => true,            // HTTPS でのみ送る
        ],
    );
    オプション 役割
    expires 有効期限。未指定はブラウザ閉じるまで
    httponly JavaScript からアクセス禁止 (XSS で盗まれにくくする)
    samesite 他サイトからのリクエストに乗せない (CSRF 対策)
    secure HTTPS でのみ送信

    → 本番では httponly + samesite=Lax + secure が基本セット。

  5. 採点用スタブ: stdin から $_COOKIE を埋める

    CLI 採点ランナーには ブラウザが居ない ので、$_COOKIE が自動で埋まらない。 web トピックの $_GET と同じ要領で stdin から組み立てる:

    <?php
    // 採点用: stdin の 1 行目 (例 "name=太郎") を $_COOKIE に展開
    $line = trim(fgets(STDIN) ?: '');
    parse_str($line, $_COOKIE);
    
    // 以降は本物の Web と同じ
    $name = $_COOKIE['name'] ?? 'guest';
    echo "こんにちは、{$name}さん\n";
    • parse_str("name=太郎", $_COOKIE) で連想配列に分解
    • 本物の Web では PHP が $_COOKIE を自動で埋めるので、このスタブは不要
  6. Cookie はブラウザに改ざんできる ← 必ず覚える

    // ❌ 危ない例
    setcookie('user_id', '42');
    $userId = $_COOKIE['user_id'];   // ユーザーが 1 や 999 に書き換えられる
    • ブラウザの開発者ツールから Cookie の値はいくらでも書き換えられる
    • ログイン状態や権限など、改ざんされると困る情報を Cookie に直接置かない
    • 「ユーザーが好き勝手に値を入れる入力欄」と思って扱う

    → そういう情報は Session に入れて、Cookie には Session ID (合言葉) だけ 入れる (ch02 の話)。

  7. このチャプターでできるようになること

    setcookie('key', 'value') でブラウザに Cookie を書ける ✅ $_COOKIE['key'] でブラウザから送られた Cookie を読める ✅ httponly / samesite / secure の役割を 1 行で言える ✅ Cookie はブラウザに改ざんされるため、秘密情報は入れないと判断できる

    → ドリルへ

1 / 7
📜 スライドを全部一気に読む(縦表示)

Lesson 13 / Chapter 3


Cookie のやり取り (絵)

1. ブラウザがリクエスト
   GET / HTTP/1.1

2. サーバーがレスポンスに Set-Cookie ヘッダを乗せる
   HTTP/1.1 200 OK
   Set-Cookie: name=taro

3. ブラウザが Cookie を保存する

4. 次回以降のリクエストに自動で乗せて送る
   GET /page HTTP/1.1
   Cookie: name=taro

PHP からは:

  • 書き出す: setcookie('name', 'taro')
  • 読む: $_COOKIE['name'] (連想配列)

最小のサンプル

<?php
// 1. ブラウザに Cookie を書く (echo より前で呼ぶ)
setcookie('name', '太郎');

// 2. 次回以降、ブラウザが送ってきた Cookie を読む
$name = $_COOKIE['name'] ?? 'guest';
echo "こんにちは、{$name}さん\n";
  • setcookie()echo の前 で呼ぶ (HTTP ヘッダは本文より前に送る必要がある)
  • 初回アクセス時は $_COOKIE は空 → ??guest にフォールバック
  • リロードすると Cookie が乗ってきて 太郎 が出る

setcookie() のオプション (重要 3 つ)

setcookie(
    'name',           // key
    '太郎',           // value
    [
        'expires'  => time() + 3600,   // 1 時間後に消える
        'httponly' => true,            // JS から読めない (XSS 対策)
        'samesite' => 'Lax',           // CSRF 対策
        'secure'   => true,            // HTTPS でのみ送る
    ],
);
オプション 役割
expires 有効期限。未指定はブラウザ閉じるまで
httponly JavaScript からアクセス禁止 (XSS で盗まれにくくする)
samesite 他サイトからのリクエストに乗せない (CSRF 対策)
secure HTTPS でのみ送信

→ 本番では httponly + samesite=Lax + secure が基本セット。


採点用スタブ: stdin から $_COOKIE を埋める

CLI 採点ランナーには ブラウザが居ない ので、$_COOKIE が自動で埋まらない。 web トピックの $_GET と同じ要領で stdin から組み立てる:

<?php
// 採点用: stdin の 1 行目 (例 "name=太郎") を $_COOKIE に展開
$line = trim(fgets(STDIN) ?: '');
parse_str($line, $_COOKIE);

// 以降は本物の Web と同じ
$name = $_COOKIE['name'] ?? 'guest';
echo "こんにちは、{$name}さん\n";
  • parse_str("name=太郎", $_COOKIE) で連想配列に分解
  • 本物の Web では PHP が $_COOKIE を自動で埋めるので、このスタブは不要

Cookie はブラウザに改ざんできる ← 必ず覚える

// ❌ 危ない例
setcookie('user_id', '42');
$userId = $_COOKIE['user_id'];   // ユーザーが 1 や 999 に書き換えられる
  • ブラウザの開発者ツールから Cookie の値はいくらでも書き換えられる
  • ログイン状態や権限など、改ざんされると困る情報を Cookie に直接置かない
  • 「ユーザーが好き勝手に値を入れる入力欄」と思って扱う

→ そういう情報は Session に入れて、Cookie には Session ID (合言葉) だけ 入れる (ch02 の話)。


このチャプターでできるようになること

setcookie('key', 'value') でブラウザに Cookie を書ける ✅ $_COOKIE['key'] でブラウザから送られた Cookie を読める ✅ httponly / samesite / secure の役割を 1 行で言える ✅ Cookie はブラウザに改ざんされるため、秘密情報は入れないと判断できる

→ ドリルへ

この章で取り組む 演習問題の流れ (2ステップ)
  1. 01 ドリル 01 — stdin から `$_COOKIE['name']` を組み立てて出力 README.md starter.php answer.php
  2. 02 ドリル 02 — 複数 Cookie を読んで一覧出力 README.md starter.php answer.php

演習問題の詳細

この章の演習問題の内容を読めます。実際に手元で解くには教材リポジトリを clone してください。

ドリル 01 — stdin から `$_COOKIE['name']` を組み立てて出力

問題

採点ランナーは CLI 直実行なので、answer.php の冒頭で 標準入力の 1 行を Cookie 文字列として parse_str$_COOKIE に展開 してください (スタブはコードに含めて構いません)。

$_COOKIE['name'] を取り出し、"こんにちは、{name}さん" を 1 行出力してください。name が無ければ 'guest' をフォールバックとして使ってください。

このドリルの入力例 (tests/input.txt):

name=太郎

期待される出力:

こんにちは、太郎さん

ヒント

$line = trim(fgets(STDIN) ?: '');
parse_str($line, $_COOKIE);
$name = $_COOKIE['name'] ?? 'guest';
echo "こんにちは、{$name}さん\n";

本物の Cookie 動作で確認したい場合

cd topics/session-cookie/ch03-cookie-basic/drill/01-read-cookie/
php -S localhost:8000 answer.php

ブラウザの開発者ツール (Application → Cookies) で name=太郎 を手動追加してリロード。

🧪 ブラウザで試す

スライドのコードを写経して ▶ 実行、自分で書いて 📝 採点 で答え合わせ。初回のみ PHP ランタイム読込で数秒かかります。

PHP ランタイム未読込

          

        

ドリル 02 — 複数 Cookie を読んで一覧出力

問題

採点ランナーは複数行の入力を流し込みます。各行が 1 つの Cookie (key=value) を表します。

  • 各行を parse_str$_COOKIE累積展開してください
  • 最終的な $_COOKIE を、key=value の形で 入力された順に 1 行ずつ出力 してください

このドリルの入力例 (tests/input.txt):

name=太郎
lang=ja
theme=dark

期待される出力:

name=太郎
lang=ja
theme=dark

ヒント

$_COOKIE = [];
while (($line = fgets(STDIN)) !== false) {
    $line = trim($line);
    if ($line === '') continue;
    $pair = [];
    parse_str($line, $pair);
    $_COOKIE = array_merge($_COOKIE, $pair);
}
foreach ($_COOKIE as $k => $v) {
    echo "{$k}={$v}\n";
}

本物の Cookie 動作で確認したい場合

cd topics/session-cookie/ch03-cookie-basic/drill/02-multiple-cookies/
php -S localhost:8000 answer.php

ブラウザの開発者ツールから複数の Cookie を手動追加してリロード。

🧪 ブラウザで試す

スライドのコードを写経して ▶ 実行、自分で書いて 📝 採点 で答え合わせ。初回のみ PHP ランタイム読込で数秒かかります。

PHP ランタイム未読込

          

        

演習問題(2問)

  1. ドリル 01 — stdin から `$_COOKIE['name']` を組み立てて出力

    README.md starter.php answer.php

  2. ドリル 02 — 複数 Cookie を読んで一覧出力

    README.md starter.php answer.php

サイト内で問題文・雛形・解答例を確認できます。実際に手元で解くには教材リポジトリを clone してください。

完了にすると進捗に反映されます