# ch06 — 簡易ルーター (REQUEST_METHOD + REQUEST_URI 分岐)

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

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

## 本文

# ch06 — 簡易ルーター (REQUEST_METHOD + REQUEST_URI 分岐)

## 概要

実際の Web アプリは「ホーム」「ユーザー一覧」「投稿フォーム」など **複数の URL** を扱う。これを 1 つの PHP ファイルで捌くのが **ルーター (Router)** の役割。最小実装は驚くほど単純で、`$_SERVER['REQUEST_METHOD']` (GET/POST) と `$_SERVER['REQUEST_URI']` (`/users` などのパス) を見て `if` か `match` で分岐するだけ。

これは **フロントコントローラ・パターン** と呼ばれ、Laravel や Symfony でも考え方は同じ。フレームワークがやっているのは、この `if-else` を `Route::get('/users', fn() => ...)` のような **宣言的な書き方** に整理しているだけ。本質は `REQUEST_METHOD` × `REQUEST_URI` の分岐という生 PHP の発想と変わらない。

ドリルでは `GET /` → home、`GET /users` → 一覧、`POST /users` → 登録、と **「メソッド × パス」の組み合わせ** で応答を分ける練習をする。「同じ URL でも GET と POST で意味が違う」考え方は REST API の基本で、ここを通っておくと後でフレームワークのコントローラ・アクションが「あの分岐をクラスに整理しただけか」と腹落ちする。

## 学習目標

- `$_SERVER['REQUEST_METHOD']` と `$_SERVER['REQUEST_URI']` を組み合わせて **「メソッド + URI」** で応答を分けられる
- 1 つの PHP で複数の URL を捌ける (フロントコントローラ・パターンの最小版)
- フレームワーク (Laravel など) のルーターが内部でやっていることをイメージできる

## 所要時間

スライド 5 分 + ドリル 3 問 = **25 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | 1 行目に method、2 行目に URI を受け取り、`GET /` のみ `"home"` を出力、その他は `"404"` |
| 02 | URI で分岐: `/users` → `"users一覧"` / `/posts` → `"posts一覧"` / その他 → `"404"` |
| 03 | method + URI で分岐: `GET /users` → `"一覧表示"` / `POST /users` → `"新規登録"` / その他 → `"404"` |

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

```bash
cd topics/web/ch06-routing-basic/drill/03-method-uri/
php -S localhost:8000 answer.php
```

ブラウザで `http://localhost:8000/users` (GET) を開く。POST は `curl` で:

```bash
curl -X POST http://localhost:8000/users
```

## スライド

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

<!--
LLM_CONTEXT:
  Lesson 12 / Chapter 6
  目的: REQUEST_METHOD と REQUEST_URI で分岐するミニルーターを書く / フレームワークが内部でやっていることを体感
  扱わない: 動的パラメータ (/users/:id) / フレームワーク (Laravel など) / 正規表現ルーティング
  読み上げ時間目安: 5 分
-->

# 簡易ルーター

Lesson 12 / Chapter 6

---

## 1 つの PHP で複数 URL を捌く

```bash
php -S localhost:8000 index.php
```

- 第 2 引数を付けて起動すると、**全リクエストが `index.php` に集まる**
- `/users` でも `/posts` でも `/admin/login` でも、全部 `index.php` が呼ばれる
- `index.php` の中で **「来た URI が何か」を見て分岐** する

→ これが **フロントコントローラ・パターン** の最小形。Laravel など本格的なフレームワークもこの構造の上に乗っている。

---

## 分岐に必要なのは 2 つ

```php
<?php
$method = $_SERVER['REQUEST_METHOD'];  // "GET" / "POST" / ...
$uri    = $_SERVER['REQUEST_URI'];     // "/users" / "/posts?page=2"
```

| 何を見るか | 例 |
|---|---|
| `REQUEST_METHOD` | `GET` / `POST` を区別 |
| `REQUEST_URI` | `/` / `/users` / `/posts` を区別 |

この 2 つの組み合わせで応答を決める。

---

## URI に query string が含まれることに注意

```
URL: http://localhost:8000/users?page=2
↓
$_SERVER['REQUEST_URI'] = "/users?page=2"   ← クエリも含む！
```

純粋なパスだけ欲しいときは `parse_url` を使う:

```php
$path = parse_url($uri, PHP_URL_PATH);  // "/users"
```

ドリルでは `?` を含まない URI を渡すので `parse_url` 必須ではないが、本物のアプリでは **必ず** これをやる。

---

## URI だけで分岐するミニ例

```php
<?php
$uri = $_SERVER['REQUEST_URI'];

if ($uri === '/users') {
    echo "users一覧\n";
} elseif ($uri === '/posts') {
    echo "posts一覧\n";
} else {
    echo "404\n";
}
```

- `if / elseif / else` のチェーンが最も読みやすい (3〜4 ルートまでなら)
- `match` 式を使うとさらに短くなる

```php
echo match ($uri) {
    '/users' => "users一覧\n",
    '/posts' => "posts一覧\n",
    default  => "404\n",
};
```

---

## method + URI の組で分岐

REST の原則: 同じ URI でも **メソッドが違えば別の操作**。

```php
<?php
$method = $_SERVER['REQUEST_METHOD'];
$uri    = $_SERVER['REQUEST_URI'];

$key = "{$method} {$uri}";   // "GET /users" のような文字列にまとめる

echo match ($key) {
    'GET /users'  => "一覧表示\n",
    'POST /users' => "新規登録\n",
    default       => "404\n",
};
```

- `"GET /users"` のような文字列にして 1 つの `match` で捌くテクニック
- フレームワークも内部では似たような table lookup をやっている

---

## ルーティングが大きくなったら**配列にする**

```php
$routes = [
    'GET /'       => 'home',
    'GET /users'  => 'users一覧',
    'POST /users' => '新規登録',
    'GET /posts'  => 'posts一覧',
];

$key = "{$method} {$uri}";
echo ($routes[$key] ?? '404') . "\n";
```

- if/elseif が増えてきたら **配列 (ルーティングテーブル)** に逃がす
- これだけで「最小 Web フレームワーク」の心臓部に近づく

---

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

✅ `REQUEST_METHOD` + `REQUEST_URI` で分岐できる
✅ 1 つの PHP で複数 URL を捌ける
✅ ルートを配列に持つと拡張しやすいと知っている
✅ フレームワークが内部でやっていることを大まかにイメージできる

→ ドリルへ。本コース最終チャプター。
