# ch05 — HTML form を組み立てて受け取る

Source: https://php-school.pages.dev/topics/web/ch05-html-form/
Site: AIと学ぶPHPの学校 (https://php-school.pages.dev)
Lesson: Web アプリ入門
Level: L4

Reference (official): https://www.php.net/manual/ja/reserved.variables.request.php

## 本文

# ch05 — HTML form を組み立てて受け取る

## 概要

ここまでで `$_GET` / `$_POST` で値を受け取れるようになった。次は **送信する側 (HTML)** を自分で書く。HTML フォームの最小構造は `<form action="..." method="post">` の中に `<input name="key">` を並べ、`<button type="submit">` を 1 つ置くだけ。`<input>` の **`name` 属性** が PHP 側の **`$_POST['name']`** のキーになる対応関係を脳に刻む。

このチャプターから、1 ファイルで **「フォームを出す側」と「フォーム送信を受ける側」を兼ねる** 書き方が出る。`$_SERVER['REQUEST_METHOD']` が `GET` なら HTML 出力、`POST` なら受信内容を出力、という分岐。フレームワークではコントローラのアクションが分かれるが、生 PHP では 1 ファイルでやるのが自然。

そして HTML 出力の **絶対の習慣** が **`htmlspecialchars()` でエスケープ**。ユーザー入力をそのまま `echo` すると、`<script>` を埋め込まれて任意の JavaScript が走る **XSS 攻撃** の入り口になる。`echo htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8')` が「ユーザー入力を画面に出すときの標準形」。反射的に書けるようにする。

## 学習目標

- `<form action="..." method="post">` の最小構造を書ける
- `<input name="key">` の `name` 属性が PHP の `$_POST['key']` と対応すると言える
- form を出す側と、その送信を受ける側 を 1 ファイル内で書ける
- 出力時に `htmlspecialchars` でエスケープする習慣がつく

## 所要時間

スライド 5 分 + ドリル 2 問 = **20 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | 指定された name 属性を持つ `<form>` 文字列を出力 |
| 02 | フォーム送信を受け取って結果ページを出力 (受け口側) |

## 本物の Web で確認したい場合

```bash
cd topics/web/ch05-html-form/drill/02-process-form/
php -S localhost:8000 answer.php
```

ブラウザで `http://localhost:8000/` を開き、フォームに入力して送信。

## スライド

---
marp: true
theme: dojo
paginate: true
size: 16:9
---

<!--
LLM_CONTEXT:
  Lesson 12 / Chapter 5
  目的: <form> の最小構造を書く / form の送信を $_POST で受け取る / htmlspecialchars でエスケープ
  扱わない: ルーティング (ch06) / CSRF 対策の本格的議論 / バリデーション
  読み上げ時間目安: 5 分
-->

# HTML form を組み立てる

Lesson 12 / Chapter 5

---

## form の最小構造

```html
<form action="/register" method="post">
  <input type="text" name="name">
  <input type="email" name="email">
  <button type="submit">送信</button>
</form>
```

| 属性 | 役割 |
|---|---|
| `action` | 送信先 URL (省略すると同じ URL に POST する) |
| `method` | `get` or `post` (大文字小文字は問わない) |
| `<input name="...">` | **送信時のキー名** ← これが `$_POST` のキーになる |

---

## name 属性が `$_POST` のキーになる

```html
<form method="post" action="/register">
  <input name="name">                  <!-- → $_POST['name'] -->
  <input name="email">                 <!-- → $_POST['email'] -->
  <button type="submit">送信</button>
</form>
```

PHP 側:

```php
<?php
$name  = $_POST['name']  ?? '';
$email = $_POST['email'] ?? '';
```

**`name="..."` を書き忘れると、その値は送信されない**。一番ハマるところ。

---

## form を出す側 / 受ける側 を 1 つの PHP で

```php
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 受け口
    $name = $_POST['name'] ?? '';
    echo "登録: " . htmlspecialchars($name) . "\n";
} else {
    // form を出す
    echo '<form method="post">';
    echo '<input name="name">';
    echo '<button type="submit">送信</button>';
    echo '</form>';
}
```

- GET でアクセスされたら form を表示
- 同じ URL に POST されたら結果を表示
- これが **1 ファイル Web アプリの基本形**

---

## 出力時の `htmlspecialchars`

```php
$name = $_POST['name'] ?? '';
echo "こんにちは、" . htmlspecialchars($name);
```

| なぜ必要か | 例 |
|---|---|
| `<` や `>` を文字としてそのまま表示 | `<b>太郎</b>` を太字にせず文字列として出す |
| **XSS 対策** (悪意あるスクリプト混入の防止) | `<script>...</script>` の混入を無効化 |

- Web で **ユーザー入力をそのまま `echo` してはいけない**
- `htmlspecialchars($s, ENT_QUOTES, 'UTF-8')` がより安全な書き方 (引用符もエスケープ)

---

## 採点向けの注意

- このコースの drill は **HTML 文字列の出力** を採点する
- ブラウザに描画される見た目ではなく、`echo` した文字列そのものが期待値と一致するか
- `htmlspecialchars` の **挙動** (`<` → `&lt;` など) を確かめるには `php -r 'echo htmlspecialchars("<b>");'` が便利

---

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

✅ `<form action method>` と `<input name>` を書ける
✅ name 属性が `$_POST` のキーになると説明できる
✅ 1 ファイルで「form を出す / form を受ける」を両方書ける
✅ 出力時は `htmlspecialchars` でエスケープする

→ ドリルへ
