採点されません。匿名です。 間違えることは学習の一部です。読むだけでもかまいません。

簡易ルーター

テクノロジ系 / web (HTTP / $_GET / $_POST / form / php -S)

簡易ルーター

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_METHODGET / 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 を捌ける

✅ ルートを配列に持つと拡張しやすいと知っている

✅ フレームワークが内部でやっていることを大まかにイメージできる

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

考えてみよう

既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。

ドリル 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

採点

php scripts/grade.php topics/web/ch06-routing-basic/drill/01-method-router/

ヒント

$_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";
}

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

問題

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

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

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

このドリルの入力例:

/users

期待される出力:

users一覧

採点

php scripts/grade.php topics/web/ch06-routing-basic/drill/02-uri-router/

ヒント

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

ドリル 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

期待される出力:

新規登録

採点

php scripts/grade.php topics/web/ch06-routing-basic/drill/03-method-uri/

ヒント

$_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 で捌く」が小ぶりなアプリのお決まりパターン。