Simular el enrutamiento de Apache mod_rewrite

La funcionalidad básica de Apache mod_rewrite se puede simular mediante una secuencia de comandos PHP a la que se hace referencia desde app.yaml, que a su vez cargará la secuencia de comandos deseada. En este ejemplo se simula el patrón de PHP habitual que espera que la variable $_GET['q'] contenga la ruta de la solicitud.

Acerca de mod_rewrite.php

Para habilitar la función mod_rewrite, tu aplicación debe incluir mod_rewrite.php, que es la secuencia de comandos que se invocará para todas las solicitudes a tu aplicación con el fin de realizar el enrutamiento de solicitudes. Como se describe en los comentarios, la secuencia de comandos comprobará la existencia de secuencias de comandos PHP de nivel raíz y las invocará mientras coloca la parte de la ruta de $_SERVER['REQUEST_URI'] en 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;

Aplicación de ejemplo

A continuación, se muestra una aplicación muy sencilla escrita para esperar $_GET['q'].

app.yaml

Como puedes ver en este archivo app.yaml, esta aplicación proporcionará dos secuencias de comandos PHP de nivel raíz y servirá archivos estáticos desde un directorio llamado 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 es un index.php de estilo de router que lee $_GET['q'] para determinar la ruta de la solicitud.

<?php

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

echo 'Welcome to the site!';

other.php

A continuación, se muestra un ejemplo de una secuencia de comandos de nivel raíz que se puede llamar directamente. Muchos frameworks de PHP tienen secuencias de comandos como install.php o update.php que se comportan de forma similar.

<?php

echo 'Welcome to the other site.';

Solicitudes de ejemplo

En el ejemplo de aplicación anterior, las siguientes solicitudes se gestionarían como se muestra a continuación.

  • / se traduce como index.php con $_GET['q'] = '/'
  • /help se traduce como index.php con $_GET['q'] = '/help'
  • /other.php se traduce como other.php con $_GET['q'] = null
  • /downloads/foo_17.png se traduce como downloads/foo_17.png

Evitar la necesidad de mod_rewrite.php

Muchos frameworks de PHP ya no dependen de $_GET['q']. En su lugar, utilizan $_SERVER['REQUEST_URI'], que funciona con y sin mod_rewrite. Por lo tanto, este último es el método preferido en App Engine.

Tal como se usa en mod_rewrite.php, un método limpio para utilizar REQUEST_URI es el siguiente:

<?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!';