模擬 Apache mod_rewrite 轉送

基本的 Apache mod_rewrite 功能可使用參照 app.yaml 的 PHP 指令碼來模擬,該指令碼會接著載入所需的指令碼。本範例模擬常見的 PHP 模式;此模式預期 $_GET['q'] 變數會包含要求路徑。

關於 mod_rewrite.php

若要啟用 mod_rewrite 功能,應用程式必須包括 mod_rewrite.php;向應用程式提出執行要求轉送的所有要求將會叫用這個指令碼。如同註解所述,指令碼會檢查根層級 PHP 指令碼是否存在,並在 $_SERVER['REQUEST_URI'] 的路徑部分放入 $_GET['q'] 變數時叫用這些指令碼。

<?php
/**
 * @file
 * Provide basic mod_rewrite like functionality.
 *
 * Pass through requests for root php files and forward all other requests to
 * index.php with $_GET['q'] equal to path. The following are examples that
 * demonstrate how a request using mod_rewrite.php will appear to a PHP script.
 *
 * - /install.php: install.php
 * - /update.php?op=info: update.php?op=info
 * - /foo/bar: index.php?q=/foo/bar
 * - /: index.php?q=/
 */

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

// Provide mod_rewrite like functionality. If a php file in the root directory
// is explicitly requested then load the file, otherwise load index.php and
// set get variable 'q' to $_SERVER['REQUEST_URI'].
if (dirname($path) == '/' && pathinfo($path, PATHINFO_EXTENSION) == 'php') {
  $file = pathinfo($path, PATHINFO_BASENAME);
}
else {
  $file = 'index.php';

  // Provide mod_rewrite like functionality by using the path which excludes
  // any other part of the request query (ie. ignores ?foo=bar).
  $_GET['q'] = $path;
}

// Override the script name to simulate the behavior without mod_rewrite.php.
// Ensure that $_SERVER['SCRIPT_NAME'] always begins with a / to be consistent
// with HTTP request and the value that is normally provided.
$_SERVER['SCRIPT_NAME'] = '/' . $file;
require $file;

範例應用程式

下方顯示一個非常簡單的應用程式,預期具有 $_GET['q']

app.yaml

如同這個 app.yaml 檔案所示,此應用程式將提供兩個根層級 PHP 指令碼,並從名為 downloads 的目錄提供靜態檔案。

application: mod_rewrite_simulator
version: 1
runtime: php55
api_version: 1

handlers:
# Example of handler which should be placed above the catch-all handler.
- url: /downloads
  static_dir: downloads

# Catch all unhandled requests and pass to mod_rewrite.php which will simulate
# mod_rewrite by forwarding the requests to index.php?q=... (or other root-level
# PHP file if specified in incoming URL.
- url: /.*
  script: mod_rewrite.php

index.php

index.php 是路由器樣式的 index.php,會讀取 $_GET['q'] 以決定要求路徑。

<?php

if ($_GET['q'] == '/help') {
  echo 'This is some help text.';
  exit;
}

echo 'Welcome to the site!';

other.php

以下是可直接呼叫的根層級指令碼範例。許多 PHP 架構擁有行為類似的指令碼,例如 install.phpupdate.php

<?php

echo 'Welcome to the other site.';

要求範例

依據上述的應用程式範例,下列要求會依所示方式處理。

  • / 翻譯為具有 $_GET['q'] = '/'index.php
  • /help 翻譯為具有 $_GET['q'] = '/help' index.php
  • /other.php 翻譯為具有 $_GET['q'] = null other.php
  • /downloads/foo_17.png 翻譯為 downloads/foo_17.png

避免需要 mod_rewrite.php

許多 PHP 架構不再依賴 $_GET['q'],而是改用 $_SERVER['REQUEST_URI'],不論是否有 mod_rewrite 皆可執行作業。後者是在 App Engine 上建議使用的方法。

如同用於 mod_rewrite.php,使用 REQUEST_URI 的乾淨方法如下所示:

<?php

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

if ($path == '/help') {
  echo 'This is some help text.';
  exit;
}

echo 'Welcome to the site!';

本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
PHP 5 適用的 App Engine 標準環境