Simuler le routage mod_rewrite d'Apache

La fonctionnalité de base Apache mod_rewrite peut être simulée à l'aide d'un script PHP référencé à partir du fichier app.yaml qui chargera ensuite le script souhaité. Cet exemple simule le schéma PHP commun qui s'attend à ce que la variable $_GET['q'] contienne le chemin d'accès de la requête.

À propos de mod_rewrite.php

Pour activer la fonctionnalité mod_rewrite, votre application doit inclure mod_rewrite.php, qui est le script qui sera appelé afin que toutes les requêtes adressées à votre application effectuent le routage des requêtes. Comme décrit dans les commentaires, le script vérifie l'existence de scripts PHP à la racine, puis les appelle tout en plaçant le chemin d'accès de $_SERVER['REQUEST_URI'] dans la variable $_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;

Exemple d'application

L'application ci-dessous a été écrite simplement pour s'attendre à recevoir $_GET['q'].

app.yaml

Comme vous pouvez le constater à partir de ce fichier app.yaml, cette application fournira deux scripts PHP racine et diffusera les fichiers statiques à partir d'un répertoire nommé 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 est un fichier routeur index.php qui lit $_GET['q'] pour déterminer le chemin d'accès de la requête.

<?php

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

echo 'Welcome to the site!';

other.php

Voici un exemple de script racine pouvant être appelé directement. De nombreux frameworks PHP contiennent des scripts comme install.php ou update.php qui se comporteraient de la même manière.

<?php

echo 'Welcome to the other site.';

Exemples de requête

Selon l'exemple d'application ci-dessus, les requêtes suivantes seraient traitées ainsi :

  • / est traduit par index.php avec $_GET['q'] = '/'
  • /help est traduit par index.php avec $_GET['q'] = '/help'
  • /other.php est traduit par other.php avec $_GET['q'] = null
  • /downloads/foo_17.png est traduit par downloads/foo_17.png

Éviter de recourir à mod_rewrite.php

De nombreux frameworks PHP ne dépendent plus de $_GET['q']. Au lieu de cela, ils utilisent $_SERVER['REQUEST_URI'], qui peut fonctionner avec et sans mod_rewrite. De ce fait, la méthode privilégiée sur App Engine est celle qui n'utilise pas mod_rewrite.

Tel qu'utilisé dans mod_rewrite.php, le code ci-dessous est une méthode simple d'utilisation de 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!';