Url Rewriting: Top 5 Ways Of PHP Url Rewriting

January 4, 2026 · Website Design

URL rewriting is the practice of turning long, parameter-heavy links into clean, readable paths that are easier to share, remember, and organise. This guide is for PHP developers and site owners who want “pretty URLs” without breaking existing links, while keeping routing predictable and SEO-friendly.

What URL rewriting actually does (and what it doesn’t)

Rewriting maps an incoming request (for example, /products/42) to a real script (for example, /product.php?id=42) without the user seeing the underlying file path. It’s different from a redirect: a rewrite is usually internal (the URL stays the same in the browser), while a redirect sends the browser to a new URL.

Good rewriting keeps URLs consistent, avoids duplicate pages, and makes it easier to evolve your site structure over time. Poor rewriting causes loops, broken assets (CSS/JS), and multiple URLs serving the same content.

1) Apache .htaccess with mod_rewrite (classic shared hosting approach)

If your site runs on Apache, the most common method is using mod_rewrite in an .htaccess file. This is ideal when you don’t control server-level config but can edit the site directory.

Example: rewrite /product/42 to product.php?id=42

RewriteEngine On

# Avoid rewriting real files/folders (important for assets and admin areas)
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# Route /product/42 to /product.php?id=42
RewriteRule ^product/([0-9]+)/?$ product.php?id=$1 [L,QSA]

Notes: QSA keeps existing query parameters; L stops processing further rules. The “real files/folders” guard prevents accidental rewriting of /css/app.css or /uploads/....

If you need authoritative reference details, the Apache documentation on rewriting is the best starting point: Apache mod_rewrite documentation.

2) Nginx rewrite rules (faster, cleaner at the server layer)

On Nginx, rewrites typically live in the server block configuration rather than a per-directory file. This is common on VPS/cloud hosting and tends to be more performant than .htaccess because rules are loaded once, not on every request.

Example: “front controller” style routing

location / {
  try_files $uri $uri/ /index.php?$query_string;
}

This pattern means: serve the file if it exists; otherwise pass the request to index.php and keep the query string. From there, PHP decides what to do. It’s simple, reliable, and works well for most applications.

3) PHP front controller routing (single entry point in code)

A front controller uses one file (often index.php) as the entry point for all requests. Your web server rewrite sends everything to that file, and PHP routes based on the path.

Basic PHP router example

<?php
// index.php
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path = rtrim($path, '/');

if ($path === '') {
  require __DIR__ . '/pages/home.php';
  exit;
}

if (preg_match('#^/product/([0-9]+)$#', $path, $m)) {
  $_GET['id'] = $m[1];
  require __DIR__ . '/pages/product.php';
  exit;
}

http_response_code(404);
require __DIR__ . '/pages/404.php';

Why this works well: you keep routing logic version-controlled with your code, can unit test it, and can enforce consistent behaviour (trailing slashes, case rules, allowed patterns). This method pairs nicely with method #1 or #2, where the server funnels requests into index.php.

4) Framework routing (Laravel, Symfony, Slim and similar)

Most PHP frameworks include a router that handles rewritten paths cleanly and securely. You define route patterns and map them to controllers, and the framework takes care of decoding parameters, middleware, and response handling.

  • Pros: cleaner organisation, built-in 404 handling, route naming, middleware for auth, and safer parameter parsing.
  • Cons: more moving parts, and you’ll still need a server rewrite rule to forward requests to public/index.php (or equivalent).

If your site is more than a handful of pages, framework routing often reduces “rewrite sprawl” because you avoid packing complex rules into server configuration.

5) PHP development server routing (useful for local development and quick demos)

For local development, PHP’s built-in server can route requests through a “router script” so you can simulate pretty URLs without touching Apache/Nginx config. This is not intended for production, but it’s very handy while building.

Run a local server with a router file

php -S localhost:8000 router.php

Simple router.php

<?php
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$file = __DIR__ . $path;

// Serve existing files directly (CSS/JS/images)
if ($path !== '/' && file_exists($file) && !is_dir($file)) {
  return false;
}

// Otherwise route into index.php
require __DIR__ . '/index.php';

This mirrors the “try files, else index.php” approach you’d use in production, so behaviour stays consistent between environments.

Best practices to avoid common URL rewriting problems

Choose one canonical URL format

Decide whether URLs should end with a trailing slash (for example, /blog/) or not (/blog) and enforce it consistently. If both work, you can accidentally create duplicates that split signals and analytics.

Use redirects when changing old URLs

If you’re replacing an older pattern (like /product.php?id=42) with a new one (/product/42), use a 301 redirect from the old to the new. Rewriting alone won’t tell search engines which version is preferred.

Don’t rewrite real files and admin paths

Always protect static assets and sensitive paths. The “skip real files/folders” guard is essential so your CSS, images, and uploads don’t become accidental 404s or route into application code.

Validate route parameters

Even with neat URLs, treat path segments as untrusted input. Use allow-lists (numbers for IDs, known slugs for categories), and apply prepared statements when querying databases.

Log and test edge cases

Test double slashes, uppercase paths, missing IDs, and unexpected characters. Add logging for 404s and redirect loops, and review it after releases.