Newer
Older
hello-programmer-world / src / pages / php / 035-session.mdx
@h.sakamoto h.sakamoto 16 hours ago 6 KB work
---
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を使ってより実践的なクイズアプリを作ってみましょう。