ch06 6章中 6章目

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

スライドで見る

この章を AI と学ぶ

💬 AI に聞く質問例 3 件
  1. 「ch06 — 簡易ルーター (REQUEST_METHOD + REQUEST_URI 分岐)」のつまずきやすいポイントを、初学者向けに3つ教えてください

    ChatGPT Claude Gemini

  2. 「ch06 — 簡易ルーター (REQUEST_METHOD + REQUEST_URI 分岐)」について、自分の手で試せる練習問題を3つ出してください (難易度を上げながら)

    ChatGPT Claude Gemini

  3. 「ch06 — 簡易ルーター (REQUEST_METHOD + REQUEST_URI 分岐)」を学んだ後、次に学ぶと良いトピックは何ですか?理由も教えてください

    ChatGPT Claude Gemini

概要

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

これは フロントコントローラ・パターン と呼ばれ、Laravel や Symfony でも考え方は同じ。フレームワークがやっているのは、この if-elseRoute::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 など) のルーターが内部でやっていることをイメージできる

ドリル

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 で確認したい場合

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

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

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

解説スライド 全 8 枚

右の ボタン キー(またはスワイプ)で次のスライドに進めます。 下の「縦表示」を開くと全スライドを一気に読めます。

  1. 簡易ルーター

    Lesson 12 / Chapter 6

  2. 1 つの PHP で複数 URL を捌く

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

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

  3. 分岐に必要なのは 2 つ

    <?php
    $method = $_SERVER['REQUEST_METHOD'];  // "GET" / "POST" / ...
    $uri    = $_SERVER['REQUEST_URI'];     // "/users" / "/posts?page=2"
    何を見るか
    REQUEST_METHOD GET / POST を区別
    REQUEST_URI / / /users / /posts を区別

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

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

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

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

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

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

  5. URI だけで分岐するミニ例

    <?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 式を使うとさらに短くなる
    echo match ($uri) {
        '/users' => "users一覧\n",
        '/posts' => "posts一覧\n",
        default  => "404\n",
    };
  6. method + URI の組で分岐

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

    <?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 をやっている
  7. ルーティングが大きくなったら配列にする

    $routes = [
        'GET /'       => 'home',
        'GET /users'  => 'users一覧',
        'POST /users' => '新規登録',
        'GET /posts'  => 'posts一覧',
    ];
    
    $key = "{$method} {$uri}";
    echo ($routes[$key] ?? '404') . "\n";
    • if/elseif が増えてきたら 配列 (ルーティングテーブル) に逃がす
    • これだけで「最小 Web フレームワーク」の心臓部に近づく
  8. このチャプターでできるようになること

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

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

1 / 8
📜 スライドを全部一気に読む(縦表示)

Lesson 12 / Chapter 6


1 つの PHP で複数 URL を捌く

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

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


分岐に必要なのは 2 つ

<?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 を使う:

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

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


URI だけで分岐するミニ例

<?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 式を使うとさらに短くなる
echo match ($uri) {
    '/users' => "users一覧\n",
    '/posts' => "posts一覧\n",
    default  => "404\n",
};

method + URI の組で分岐

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

<?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 をやっている

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

$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 を捌ける ✅ ルートを配列に持つと拡張しやすいと知っている ✅ フレームワークが内部でやっていることを大まかにイメージできる

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

この章で取り組む 演習問題の流れ (3ステップ)
  1. 01 ドリル 01 — `GET /` のみ受け付けるミニルーター README.md starter.php answer.php
  2. 02 ドリル 02 — URI で分岐するルーター README.md starter.php answer.php
  3. 03 ドリル 03 — method + URI の組で分岐 (REST 風) README.md starter.php answer.php

演習問題の詳細

この章の演習問題の内容を読めます。実際に手元で解くには教材リポジトリを clone してください。

ドリル 01 — `GET /` のみ受け付けるミニルーター

問題

$_SERVER['REQUEST_METHOD']$_SERVER['REQUEST_URI'] を見て、次の通り応答する PHP を書いてください。

  • method が GET かつ URI が / のとき → "home" を 1 行出力
  • それ以外 → "404" を 1 行出力

採点ランナーは CLI 直実行なので、冒頭で stdin の 1 行目を method、2 行目を URI として $_SERVER に代入してください。

このドリルの入力例:

GET
/

期待される出力:

home

ヒント

$_SERVER['REQUEST_METHOD'] = trim(fgets(STDIN) ?: '');
$_SERVER['REQUEST_URI']    = trim(fgets(STDIN) ?: '');

if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/') {
    echo "home\n";
} else {
    echo "404\n";
}

🧪 ブラウザで試す

スライドのコードを写経して ▶ 実行、自分で書いて 📝 採点 で答え合わせ。初回のみ PHP ランタイム読込で数秒かかります。

PHP ランタイム未読込

          

        

ドリル 02 — URI で分岐するルーター

問題

$_SERVER['REQUEST_URI'] を見て、次の通り応答する PHP を書いてください。

  • /users"users一覧" を 1 行出力
  • /posts"posts一覧" を 1 行出力
  • それ以外 → "404" を 1 行出力

採点ランナーは CLI 直実行なので、冒頭で stdin の 1 行$_SERVER['REQUEST_URI'] に代入してください。

このドリルの入力例:

/users

期待される出力:

users一覧

ヒント

$_SERVER['REQUEST_URI'] = trim(fgets(STDIN) ?: '');
echo match ($_SERVER['REQUEST_URI']) {
    '/users' => "users一覧\n",
    '/posts' => "posts一覧\n",
    default  => "404\n",
};

🧪 ブラウザで試す

スライドのコードを写経して ▶ 実行、自分で書いて 📝 採点 で答え合わせ。初回のみ PHP ランタイム読込で数秒かかります。

PHP ランタイム未読込

          

        

ドリル 03 — method + URI の組で分岐 (REST 風)

問題

$_SERVER['REQUEST_METHOD']$_SERVER['REQUEST_URI'] の組み合わせで、次の通り応答する PHP を書いてください。

  • GET /users"一覧表示" を 1 行出力
  • POST /users"新規登録" を 1 行出力
  • それ以外 → "404" を 1 行出力

採点ランナーは CLI 直実行なので、冒頭で stdin の 1 行目を method、2 行目を URI として $_SERVER に代入してください。

このドリルの入力例:

POST
/users

期待される出力:

新規登録

ヒント

$_SERVER['REQUEST_METHOD'] = trim(fgets(STDIN) ?: '');
$_SERVER['REQUEST_URI']    = trim(fgets(STDIN) ?: '');

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

METHOD URI という文字列にまとめて 1 つの match で捌く」が小ぶりなアプリのお決まりパターン。

🧪 ブラウザで試す

スライドのコードを写経して ▶ 実行、自分で書いて 📝 採点 で答え合わせ。初回のみ PHP ランタイム読込で数秒かかります。

PHP ランタイム未読込

          

        

演習問題(3問)

  1. ドリル 01 — `GET /` のみ受け付けるミニルーター

    README.md starter.php answer.php

  2. ドリル 02 — URI で分岐するルーター

    README.md starter.php answer.php

  3. ドリル 03 — method + URI の組で分岐 (REST 風)

    README.md starter.php answer.php

サイト内で問題文・雛形・解答例を確認できます。実際に手元で解くには教材リポジトリを clone してください。

完了にすると進捗に反映されます