# ch03 — `$_GET` でクエリ文字列を受け取る

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

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

## 本文

# ch03 — `$_GET` でクエリ文字列を受け取る

## 概要

URL の末尾に付く `?name=太郎&age=20` の部分を **クエリ文字列** と呼ぶ。Web で最もよく使われる「ブラウザからサーバーへ値を渡す方法」で、PHP では **`$_GET` 連想配列** から取り出せる。`$_GET['name']` で `'太郎'`、`$_GET['age']` で `'20'` というシンプルな関係。

ここで必ずぶつかるのが **キーが無かったときの Warning**。`?name=太郎` しか無いのに `$_GET['age']` を読むと未定義キーで警告が出る。これを防ぐのが **`null` 合体演算子 `??`** で、`$_GET['age'] ?? '不明'` と書けば「無ければ `'不明'`」になる。Web で値を受け取る全場面で使うイディオム。

採点ランナーは CLI なので、`$_GET` を **stdin から `parse_str` で組み立てるスタブ** が冒頭に入っている。`parse_str('name=太郎&age=20', $_GET)` の 1 行で文字列を配列に展開する関数。`php -S` で動かすときはブラウザの URL に `?name=...` を付けるだけで `$_GET` に勝手に入ってくる。

## 学習目標

- URL の `?key=value&key2=value2` を `$_GET` 連想配列で受け取れる
- `$_GET['key'] ?? 'default'` で **欠落に強い** コードを書ける
- 採点用に **stdin から query string を `parse_str` で `$_GET` に組み立てる** 書き方を知る

## 所要時間

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

## ドリル

| no | 内容 |
|---|---|
| 01 | `name=太郎` を受け取り `"こんにちは、太郎さん"` を出力 |
| 02 | `name=太郎&age=20` を受け取り `"太郎 (20歳)"` を出力 |

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

```bash
cd topics/web/ch03-get-params/drill/01-get-name/
php -S localhost:8000 answer.php
```

ブラウザで `http://localhost:8000/?name=太郎` を開く (URL に `?name=...` を付けるのを忘れない)。

## スライド

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

<!--
LLM_CONTEXT:
  Lesson 12 / Chapter 3
  目的: $_GET でクエリ文字列を受け取る / 欠落に強い書き方 (?? 演算子)
  扱わない: $_POST (ch04) / form (ch05) / ルーティング (ch06)
  読み上げ時間目安: 4 分半
-->

# `$_GET` でクエリを受け取る

Lesson 12 / Chapter 3

---

## URL の `?key=value` は連想配列に化ける

```
http://localhost:8000/?name=太郎&age=20
                       ─────────────
                       これが $_GET になる
```

PHP からの見え方:

```php
<?php
$_GET = [
    'name' => '太郎',
    'age'  => '20',   // ← 文字列として入ることに注意
];
```

- `?` の後ろの `key=value&key=value` を **PHP が自動で連想配列に分解** してくれる
- 値は **常に文字列** (`age` も `"20"` であって整数 20 ではない)

---

## 最小のサンプル

```php
<?php
$name = $_GET['name'] ?? 'guest';
echo "こんにちは、{$name}さん\n";
```

URL ごとの出力:

| URL | 出力 |
|---|---|
| `/?name=太郎` | `こんにちは、太郎さん` |
| `/?name=花子` | `こんにちは、花子さん` |
| `/` (name 無し) | `こんにちは、guestさん` |

`??` は web トピックで覚えるべき小道具 No.1。**「無ければ既定値」** を 1 行で書ける。

---

## なぜ `??` を使うのか

```php
// ❌ 警告が出る (Undefined array key "name")
$name = $_GET['name'];

// ✅ 欠落していても落ちない
$name = $_GET['name'] ?? 'guest';
```

- Web では **URL に何が付いているか分からない** のが普通
- いちいち `isset($_GET['name'])` を書くより `??` が短くて読みやすい
- 「Web の入力は信用しない」 — 必ず欠落・想定外を考える癖をつける

---

## 採点用スタブ: stdin で `$_GET` を埋める

```php
<?php
// 採点用: 標準入力の 1 行目 (例 "name=太郎&age=20") を $_GET に展開
$query = trim(fgets(STDIN) ?: '');
parse_str($query, $_GET);

// 以降は本物の Web と同じ
$name = $_GET['name'] ?? 'guest';
echo "こんにちは、{$name}さん\n";
```

- `parse_str("name=太郎&age=20", $_GET)` で **URL クエリ文字列を連想配列に分解**
- 本物の Web では PHP が自動で `$_GET` を埋めるので、このスタブは要らない
- 採点ランナーは CLI なので、stdin で query string を渡してこのスタブを動かす

---

## 値が文字列であることに注意

```php
$age = $_GET['age'] ?? '0';
echo $age + 1;       // 21 (PHP が自動で数値に変換)
echo gettype($age);  // string ← あくまで文字列

// 比較で罠
if ($age == 20)  { ... }  // OK (緩い比較で文字列 "20" と整数 20 を一致扱い)
if ($age === 20) { ... }  // NG (型まで一致しない)
```

整数として扱いたいなら **明示的に `(int)$age`** にキャストする習慣を。

---

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

✅ URL の `?name=...&age=...` を `$_GET` で受け取れる
✅ `$_GET['name'] ?? 'guest'` で欠落に備えられる
✅ `parse_str` で文字列を連想配列に分解できると知っている
✅ `$_GET` の値が文字列であることを認識している

→ ドリルへ
