---
layout: "@/layouts/MarkdownLayout.astro"
---
import Toc from "../../components/Toc.astro";
import Details from "@/components/Details.astro";
export const title = "Sessionで状態を保持する";
import DockerLink from "@/components/DockerLink.astro";
# {title}
これまで学んだPHPは、ページを表示するたびに毎回新しく実行されていました。
しかし、ウェブアプリケーションでは「ログイン状態を保持する」「カートの中身を覚えておく」といった、複数のページにまたがって情報を保持したい場面があります。
このような場合に使うのが**Session(セッション)**です。
## TOC
## Sessionとは
Sessionは、ウェブサイトを訪れたユーザーごとに情報を保存する仕組みです。
たとえば、以下のような場面で使われます:
- ログイン状態の保持
- ショッピングカートの中身の保存
- 複数ページにまたがるアンケートフォーム
- クイズの進行状況の管理
### Sessionの仕組み
1. ユーザーが初めてサイトを訪れると、サーバーは**Session ID**という識別番号を発行します
2. この番号は**Cookie**としてブラウザに保存されます
3. ユーザーが次のページを訪れると、ブラウザはこの番号をサーバーに送ります
4. サーバーは番号を使って、そのユーザー専用のデータを取り出します
つまり、**ユーザーごとに専用の保存場所**が用意されるイメージです。
## Sessionの基本的な使い方
Sessionを使うには、必ず最初に`session_start()`という関数を呼び出します。
### 1. Sessionを開始する
```php
<?php
session_start(); // 必ず最初に呼び出す
?>
```
**重要:** `session_start()`は、HTMLの出力やechoの前に呼び出す必要があります。
<Details summary="なぜHTMLより前に書く必要があるのか">
Sessionの仕組み上、HTTPヘッダーという特別な情報をブラウザに送る必要があります。
このヘッダーは、HTMLなど他の出力より前に送信しなければならないというルールがあります。
もしHTMLを出力した後に`session_start()`を呼ぶと、以下のようなエラーが表示されます:
```
Warning: session_start(): Cannot send session cookie - headers already sent
```
</Details>
### 2. Sessionにデータを保存する
Sessionにデータを保存するには、`$_SESSION`という特別な配列を使います。
```php
<?php
session_start();
// Sessionにデータを保存
$_SESSION["username"] = "田中太郎";
$_SESSION["score"] = 100;
?>
```
### 3. Sessionからデータを取り出す
別のページでも、同じように`$_SESSION`配列からデータを取り出せます。
```php
<?php
session_start();
// Sessionからデータを取り出す
$username = $_SESSION["username"] ?? "ゲスト";
$score = $_SESSION["score"] ?? 0;
echo "ようこそ、{$username}さん!";
echo "現在のスコア: {$score}点";
?>
```
`??`演算子を使うことで、Sessionにデータがない場合のデフォルト値を設定できます。
### 4. Sessionのデータを削除する
特定のデータだけを削除する場合:
```php
<?php
session_start();
// 特定のデータを削除
unset($_SESSION["score"]);
?>
```
すべてのSessionデータを削除する場合:
```php
<?php
session_start();
// すべてのSessionデータを削除
session_destroy();
?>
```
## 実践例:訪問カウンター
訪問回数を記録する簡単なアプリを作ってみましょう。
<DockerLink href="sample/php/session/counter.php" />
```php file=public/sample/php/session/counter.php collapse={17-52}
public/sample/php/session/counter.php
内容を取得できませんでした
```
このアプリでは:
1. 初めて訪れた時は訪問回数を0に初期化
2. ページを表示するたびに回数を1増やす
3. ページをリロードすると回数が増える
4. 別のブラウザで開くと、また1からカウントが始まる
このように、Sessionを使えば**ユーザーごとに異なる情報**を保持できます。
## Sessionを使う際の注意点
### 1. 必ずsession_start()を呼び出す
Sessionを使うすべてのページで、最初に`session_start()`を呼び出す必要があります。
### 2. セキュリティに注意する
Sessionには重要な情報を保存できますが、以下の点に注意してください:
- パスワードなどの機密情報は暗号化する
- Sessionのタイムアウトを適切に設定する
- Session IDの固定化攻撃に注意する
### 3. データの管理に注意する
`$_SESSION`には文字列だけでなく、数値や配列も保存できます。
```php
<?php
session_start();
// 文字列
$_SESSION["name"] = "田中";
// 数値
$_SESSION["age"] = 25;
// 配列
$_SESSION["items"] = ["りんご", "バナナ", "みかん"];
?>
```
便利ですが、何を保存したか分からなくなりやすいので、本当に必要なものだけを保存するようにしましょう。
## Sessionの削除タイミング
Sessionデータは以下のタイミングで削除されます:
1. **session_destroy()を呼び出した時**
2. **一定時間アクセスがなかった時**(デフォルトは24分程度)
3. **ブラウザのCookieを削除した時**
ログアウト機能を実装する場合は、明示的に`session_destroy()`を呼び出します。
```php
<?php
session_start();
session_destroy(); // すべてのSessionデータを削除
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログアウト</title>
</head>
<body>
<p>ご利用ありがとうございました!</p>
</body>
</html>
```
## まとめ
Sessionを使うことで、複数のページにまたがって情報を保持できるようになりました。
**Sessionの基本:**
- `session_start()` - Sessionを開始(必ず最初に呼ぶ)
- `$_SESSION["キー"]` - データの保存と取り出し
- `unset($_SESSION["キー"])` - 特定のデータを削除
- `session_destroy()` - すべてのSessionを削除
**使用例:**
- ログイン状態の管理
- フォームの入力内容の一時保存
- クイズの問題と正解の管理
- ショッピングカート
**Sessionデータの管理について:**
Sessionには様々な型のデータを保存できますが、何を保存したか分からなくなりがちです。
本当に必要なものだけを保存するようにしましょう。
また、どんなデータが入っているか、コメントで記録しておくと良いでしょう。
```php
// $_SESSION["user_id"] は整数(ユーザーID)
$_SESSION["user_id"] = 123;
// $_SESSION["cart"] は配列(商品IDの配列)
$_SESSION["cart"] = [1, 5, 8];
```
次の演習では、このSessionを使ってより実践的なクイズアプリを作ってみましょう。