こんにちは、カヨです。
リクエストをPHP経由で適切なコンテンツに振り分ける処理
IIS設定のURL書き換え設定をしなければならないプロジェクト(WEBサイト)があり、その中の仕組みをわからないままだったので改めに内容を読んでみました。「自分でコードを新規で書くのは好き。」でそれはやる人多いしかっこいい感じするけど、以前からあるコードを読み解く方がずっと難しいきがする。不要コードとか、謎の未使用関数とか遺跡のようにでてくるのを解読して追加のコンテンツを作成しているのですが全然評価してもらえないのが悲しいところ。
✔︎IISのSSIをせずにSSIの処理を設置したい人
✔リクエストをPHPファイル(機能を設置するPHPファイル)にリダイレクトしてもとのURLに戻す処理を書きたい人
✔IISでリダイレクト処理を設定したい人
前提
・IISにURL書き換えモジュールを導入済 → まだの方はこちらの記事
・Windows
・PHPをPCに導入済 → まだの方はこちらの記事
・WEBサイトをPCで作成や修正している
「SSIの代替としてPHPを活用し、 リクエストをPHP経由で適切なコンテンツに振り分ける処理する」手順
①IISでリダイレクト設定
✔IISで設定画面を開く
⇒ IISを開く > 対象のサイトを選択 > URL書き換え
✔規則の追加をする
✔規則の追加「テンプレート選択」
⇒空の規則 > OK
✔設定画面
設定によって設定する箇所は変わりますが今回は以下です。
要求されたURL:パターンに一致する
使用:正規表現
パターン:^(.*)$
大文字と小文字を区別しない:✅
条件:※後程詳細記載します
アクションの種類:書き換え
URLの書き換え:/router.php?request_url=/{R:1}
クエリ文字列の追加:✅
※この設定だけがすべてではありません。また、設定についての責任は負いません。

【URLの書き換え:/router.php?request_url=/{R:1}】の部分のrouter.phpもファイル名はphpの機能にあったものなら名前は別のものでも大丈夫◎この名前はphpファイル作成時に必要になるので控えておこう。
✔設定画面(条件)
⇒すべて一致になってることを確認 > 追加
⇒追加の条件 > 「条件」に追加されてるか確認
入力文字列が次の条件を満たしているかチェック: パターンに一致しない
パターン: ^(.*).(gif|png|jpg|jpeg|css|svg|icon|js|pdf|xml|mp4|webp)$
大文字小文字の区別をしない:✅
・{REQUEST_FILENAME}(リクエストされたファイル名)が、^(.*).(gif|png|jpg|jpeg|css|svg|…) のパターンに一致しない場合に適用。
・これは画像やCSS、SVGなどの特定のファイル拡張子を持つリクエストは除外するという条件。
※この設定だけがすべてではありません。また、設定についての責任は負いません。
※パターンにwebpも追記2025.03.24。webpを表示するにはIISのMIME設定がいります。
✔全部設定できたら適用
✔追加済を確認
設定したものがここに出てきたらIISの設定はOK 。
IISの再起動もしておこう。
②phpファイルを用意する
IISでは今から作成するファイルにリダイレクトする設定をしてきました。言い換えると、リクエストを受けたURL先に行く前にphpファイルの中の処理をさせる設定をIISに設定、phpには先ほど受けた本来のURL先に移動するようにしていきます。このことで、ページを開く前にphpの中に書いた処理を挟むことができます。
✔phpファイル
先ほどIISのURL書き換えで「router.php」と名前を付けたファイルの中身です。
<?php
$request_url = filter_input(INPUT_GET, 'request_url');
$DOCUMENT_ROOT = filter_input(INPUT_SERVER, 'DOCUMENT_ROOT');
$file_path = $DOCUMENT_ROOT . str_replace('/', '\\', $request_url);
if (!file_exists($file_path)) {
header('HTTP/1.0 404 Not Found');
exit;
}
$content_type = 'Content-Type: ' . mime_content_type($file_path);
header($content_type);
include_once($file_path);
大まかに、リクエストされた元のURL情報をもって、このファイルに来て元のURLを再度組みなおして本来のURL先に移動するながれです。
内容の詳細を見ていきましょう!
1. もとのURLを取得する処理
$request_url = filter_input(INPUT_GET, 'request_url');
・IISのリライトルールで渡された request_url を取得
・これが 元のリクエストされたURL(例: /some-page)
2. 取得したURLをファイルパスに変換
$DOCUMENT_ROOT = filter_input(INPUT_SERVER, 'DOCUMENT_ROOT');
$file_path = $DOCUMENT_ROOT . str_replace('/', '\\', $request_url);
・DOCUMENT_ROOT(サイトのルートディレクトリ)と request_url を結合
・Windows環境では / を \ に変換してファイルパスを生成
3. ファイルが存在するかチェック
if (!file_exists($file_path)) {
header('HTTP/1.0 404 Not Found');
exit;
}
・該当するファイルがない場合は 404 Not Found を返して終了
・存在するなら次の処理へ
4. MIMEタイプを設定
$content_type = 'Content-Type: ' . mime_content_type($file_path);
header($content_type);
・リクエストされたファイルの種類を取得し、適切な Content-Type を設定
・ブラウザがファイルを正しく認識するために必要
5. ファイルを出力
include_once($file_path);
・file_path の内容を読み込んで出力
・これによって request_url に対応する元のファイルを実行・表示
✔phpファイルの位置
作成したファイル(ここではrouter.php)を配置して完了なのですがこのままではただphpファイルを通りすぎただけなので、SSIの記述を追加しましょう!これでIISに設定しなくていいので依存しない形にできます。
③phpファイルにSSIの機能を追記
ここまでのphpファイルはただファイルを経由させる流れを作成しただけなので、ファイル内を通過したさいにさせたい処理を記述します。今回はSSI共通のコンポーネントを読み込ませる機能です。
✔ssi($path) 関数
function ssi($path)
{
include_once(filter_input(INPUT_SERVER, 'DOCUMENT_ROOT') . $path);
}
・DOCUMENT_ROOT に $path を付けたファイルを include_once する。
・サーバー上のファイルを読み込むための関数。
これを追記すると経由したhtmlファイル内で以下のような共通のコンポーネントの読み込みができます。
<?= ssi("/partial/common-css.html") ?>

phpの<?から始まり、ssi₍ ₎の中に引用したいファイルパスを記入します。 これを先ほどのphpファイルに書き込むことで、SSIの機能が使えるようになります◎
✔SSIの機能を加えたファイル内全体
最後にいままで説明してきた部分をまとめた完成版のコードです
<?php
function ssi($path)
{
include_once(filter_input(INPUT_SERVER, 'DOCUMENT_ROOT') . $path);
}
// ① サーバーのルートディレクトリを取得
$DOCUMENT_ROOT = filter_input(INPUT_SERVER, 'DOCUMENT_ROOT');
// ② IISのRewriteルールで渡されたリクエストURLを取得
$request_url = filter_input(INPUT_GET, 'request_url');
// ③ リクエストされたURLを基に、サーバー上のファイルパスを構築
$file_path = $DOCUMENT_ROOT . str_replace('/', '\\', $request_url);
// $file_path = $DOCUMENT_ROOT . str_replace('//', '', $request_url); // Mac環境向けの処理(Windowsと区別)
// ④ ファイルが存在しない場合は 404エラーを返す
if (!file_exists($file_path)) {
header('HTTP/1.0 404 Not Found');
exit;
}
// ⑤ ファイルの拡張子を取得
$pathinfo = pathinfo($file_path);
// ⑥ 拡張子が存在しない場合は、デフォルトで "index.html" を補完
if (!array_key_exists('extension', $pathinfo)) {
$pathinfo['basename'] = 'index.html';
$file_path .= 'index.html';
}
// ⑦ MIMEタイプを自動判別して、適切な Content-Type を設定
$content_type = 'Content-Type: ' . mime_content_type($file_path);
header($content_type);
// ⑧ リクエストされたファイルを読み込んで表示(PHPコードがある場合は実行)
include_once($file_path);

最初にssi($path) 関数を書いて、その後がもともとリクエストでもらってたURLへ戻すコードってことですね。
お疲れ様でした!これで完成です✨
その他
✔PHPファイルの中、始まりは「<php?」だけど最後は「?>」はいらないのか。
.html内にPHPを書いたときに、<?phpは必要だけど、?>は省略可能。
✔IISでもSSI機能があるのに、なぜPHPで代替えする場合があるのか
・IISのSSIではアクセス制御ができないから
⇒PHPなら条件分岐やログ記録、承認チェックが可能
・IISのSSIは動的処理が難しい
⇒PHPのSSIならリクエストの解析や動的なページ作成ができる。
⇒例:request_urlを元に動的にページを切り替える処理
・IISのSSI機能には制約がある
⇒IISのSSIは.shtmlなどの特定の拡張子でしか動作しない
⇒PHPを使えば拡張子に関係なくファイルを処理できる
・IISのSSIは拡張性が低い
⇒PHPならデータベースとの関連やカスタム処理が可能
⇒SSIは基本的に静的なファイルの読み込みしかできない
【結論】
✅SSIの制約(アクセス制御・動的処理不可)を回避するために、PHPベースでインクルード処理を行うことがある。
✔今回行った処理「SSIの代替としてPHPを活用し、
リクエストをPHP経由で適切なコンテンツに振り分ける処理」の流れの視覚化