【PHP】PHPのクッキー(setcookie)の使い方と注意点

phpアイキャッチ PHP

こんにちは、かつコーチです。

前回は session_start を使ったセッションによるログイン状態の保持を解説しました。

セッションはサーバー側にデータを保存する仕組みでしたが、今回はブラウザ側にデータを保存する「クッキー(Cookie)」を扱います。

「ログイン状態を保持する」という目的は似ていますが、仕組みも使いどころもセッションとはかなり違うので、違いを意識しながら見ていきましょう。

クッキーとは?

ブラウザに保存される小さなデータ

クッキーとは、Webサーバーがブラウザに送り、ブラウザ側に保存してもらう小さなデータのことです。

一度クッキーを保存すると、同じサイトに再度アクセスしたときに、ブラウザがそのクッキーを自動的にサーバーへ送り返してくれます。

これによって「前回訪問したときの情報」をサーバー側が覚えていなくても、ブラウザ側の情報から利用者を判別できるようになります。

セッションとの違い

セッションとクッキーは混同されやすいので、違いを整理しておきます。

項目セッションクッキー
保存場所サーバー側ブラウザ側
保存期間基本はブラウザを閉じるまで指定した期限まで残せる
保存できるデータ量比較的大きい少量(1つあたり4KB程度)
セキュリティ比較的安全(データ自体は外に出ない)改ざん・盗み見のリスクがある
代表的な用途ログイン状態の保持「次回から自動ログイン」「表示設定の記憶」

私は最初、「ログイン状態を保持するなら何でもクッキーでいいのでは」と思っていました。

でも実際には、パスワードのような重要な情報をクッキーに直接保存するのは危険です。

クッキーはブラウザの開発者ツールから誰でも中身を見たり書き換えたりできるため、機密性の高いデータの保存には向きません。

「次回から自動ログイン」のように、なくなっても致命的ではない情報をクッキーに、パスワードなど重要な認証情報の管理はセッションやトークンに任せる、という役割分担で考えると整理しやすいです。

クッキーの基本的な使い方

手順1:クッキーをセットする

クッキーを保存するには setcookie() 関数を使います。

<?php
// クッキー名, 値, 有効期限(UNIXタイムスタンプ)
setcookie("username", "katsu_coach", time() + 60 * 60 * 24 * 30);
// 30日後まで有効なクッキーをセット
?>

time() + 60 * 60 * 24 * 30 の部分は「現在時刻から30日後」という意味です。

秒単位で計算するので、最初は少し分かりづらいですが、60秒 × 60分 × 24時間 × 30日 と考えると計算しやすくなります。

手順2:クッキーを読み取る

保存したクッキーは、$_COOKIE というスーパーグローバル変数から読み取れます。

<?php
if (isset($_COOKIE["username"])) {
    echo "おかえりなさい、" . $_COOKIE["username"] . "さん";
} else {
    echo "初めてのご訪問ですね";
}
?>

isset() でクッキーが存在するかどうかを先に確認してから使うのがポイントです。

存在しないクッキーにいきなりアクセスすると警告が出るので、必ずチェックを挟む癖をつけましょう。

手順3:クッキーを削除する

クッキーを削除するには、有効期限を過去の日時に指定して setcookie() を呼び出します。

<?php
// 有効期限を過去に設定することで削除扱いになる
setcookie("username", "", time() - 3600);
?>

「削除用の関数」があるわけではなく、「すでに期限切れのクッキーを上書きで送る」ことで、ブラウザ側から消してもらう、という発想です。

つまずきやすいポイント:出力より前に呼び出す

headers already sent エラー

クッキーを扱うときに私が何度もハマったのが、setcookie() の呼び出し位置です。

❌ Before:HTML出力の後に setcookie() を書いてしまう

<!DOCTYPE html>
<html>
<body>
<p>ようこそ</p>
<?php
setcookie("username", "katsu_coach", time() + 3600);
?>
</body>
</html>

このコードを実行すると、次のような警告が出ます。

Warning: Cannot modify header information - headers already sent by (output started at ...)

私は初めてこのエラーを見たとき、「headerって何のこと?」と全く意味が分からず、しばらく検索し続けた記憶があります。

原因は単純で、setcookie() はHTTPヘッダーという「本文より前の部分」にクッキー情報を書き込む仕組みだからです。

すでに <p>ようこそ</p> というHTML(本文)が出力された後では、ヘッダーを追加で書き換えることができません。

✅ After:ファイルの一番上、HTML出力より前で呼び出す

<?php
// 一番上でクッキーの処理をまとめて済ませておく
setcookie("username", "katsu_coach", time() + 3600);
?>
<!DOCTYPE html>
<html>
<body>
<p>ようこそ</p>
</body>
</html>

session_start() にも同じ制約がありましたが、setcookie() も同様に「必ず何かを出力するより前に呼び出す」というルールを守る必要があります。

PHPファイルの先頭にクッキーやセッションの処理をまとめておくと、このエラーを未然に防ぎやすくなります。

応用:クッキーのオプションを活用する

セキュリティを高めるオプション

setcookie() には、有効期限以外にもいくつかオプションがあります。

とくに重要なのが httponlysecure です。

<?php
setcookie(
    "username",
    "katsu_coach",
    [
        "expires" => time() + 60 * 60 * 24 * 30,
        "path" => "/",
        "secure" => true,     // HTTPS通信でのみ送信する
        "httponly" => true,   // JavaScriptからのアクセスを禁止する
        "samesite" => "Lax",  // 他サイトからの不正な送信を防ぐ
    ]
);
?>

httponlytrue にすると、JavaScriptの document.cookie からクッキーを読み取れなくなります。

これによって、悪意のあるスクリプトが埋め込まれた場合でも、クッキーの中身を盗まれるリスクを下げられます。

securetrue にすると、HTTP(暗号化なし)では送信されず、HTTPS通信のときだけクッキーが送られるようになります。

本番環境で個人情報に関わるクッキーを扱う場合は、この2つのオプションはできる限りセットで使うことをおすすめします。

Laravelではどう扱われるか

余談ですが、Laravelを使うようになると、クッキーは Cookie::queue() やレスポンスの ->cookie() メソッドで扱うようになり、httponlysecure といった安全な設定がデフォルトで有効になっています。

素のPHPで一つ一つオプションを意識する経験をしておくと、Laravelが裏側で何をやってくれているのかが感覚的に理解しやすくなります。

まとめ

この記事のポイント

  • クッキーはブラウザ側に保存される小さなデータで、setcookie() で保存する
  • セッションとは保存場所・保存期間・セキュリティ面で役割が異なる
  • 読み取りは $_COOKIE、削除は期限を過去にして再度 setcookie() を呼ぶ
  • setcookie() は必ずHTML出力より前に呼び出す(headers already sent エラーに注意)
  • httponlysecure オプションでセキュリティを高められる

次に読むべき記事

次回は、PHPでファイルを直接読み書きする方法を解説します。

会員登録データやログなど、簡単なファイル操作ができるようになると扱える処理の幅がぐっと広がります。

→ 次の記事:PHPでファイルを読み書きする方法:fopen・file_get_contentsの使い方

タイトルとURLをコピーしました