A clean URL can be easier to share and read than one containing a front-controller filename. For example, a CMS may serve the same article through a route that omits index.php. The server still runs the application dynamically; “clean” does not mean the page has become a static file.

Before: https://www.example.com/index.php/1.html
After: https://www.example.com/1.html
URL appearance alone does not guarantee better search rankings. A migration needs consistent links, appropriate redirects from old addresses, and canonical signals that agree with the intended public URL. Do not assume that a shorter path automatically indexes better.
Typecho
The following legacy rule passes requests that do not match a real file into Typecho’s front controller. Confirm that it matches your version, PHP handler, and permalink configuration before using it.
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php$1 last;
}
WordPress
A standard single-site front-controller pattern uses try_files. Existing files or directories are considered before the request is passed to index.php. PHP processing is configured separately. Multisite and subdirectory installs need different rules; consult the WordPress Nginx guide.
location /
{
try_files $uri $uri/ /index.php?$args;
}
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
Older CMS-specific examples
These are the original examples for older applications. Treat them as version-dependent references, not interchangeable configurations. The PHPCMS block also contains PHPWind rules, which should only be kept for a site that actually uses them.
Discuz:
location / {
rewrite ^/archiver/((fid|tid)-[\w\-]+\.html)$ /archiver/index.php?$1 last;
rewrite ^/forum-([0-9]+)-([0-9]+)\.html$ /forumdisplay.php?fid=$1&page=$2 last;
rewrite ^/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /viewthread.php?tid=$1&extra=page%3D$3&page=$2 last;
rewrite ^/space-(username|uid)-(.+)\.html$ /space.php?$1=$2 last;
rewrite ^/tag-(.+)\.html$ /tag.php?name=$1 last;
}
PHPCMS / PHPWind:
location / {
###PHPCMS
rewrite ^(.*)show-([0-9]+)-([0-9]+)\.html$ $1/show.php?itemid=$2&page=$3;
rewrite ^(.*)list-([0-9]+)-([0-9]+)\.html$ $1/list.php?catid=$2&page=$3;
rewrite ^(.*)show-([0-9]+)\.html$ $1/show.php?specialid=$2;
####PHPWind
rewrite ^(.*)-htm-(.*)$ $1.php?$2 last;
rewrite ^(.*)/simple/([a-z0-9\_]+\.html)$ $1/simple/index.php?$2 last;
}
Z-Blog:
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-f $request_filename){
rewrite (.*) /index.php;
}
ShopWind:
location / {
#Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php$is_args$args;
}
#If you want a single domain name at the front and back ends
location /admin {
try_files $uri $uri/ /admin/index.php$is_args$args;
}
location /mobile {
try_files $uri $uri/ /mobile/index.php$is_args$args;
}
location /api {
try_files $uri $uri/ /api/index.php$is_args$args;
}
Apply and verify
Place rules inside the appropriate server context and back up the existing configuration. Do not blindly combine every example or replace the PHP location block. Nginx’s try_files documentation explains how the fallback works.
sudo nginx -t
# Reload only if the configuration test succeeds.
sudo nginx -s reload
Check an article URL, an existing asset, a missing page, query strings, and the admin login. The examples route requests internally; they do not by themselves implement every redirect from old public URLs. Add deliberate migration redirects and verify there is no loop before relying on them for SEO.
Adapted from the original Chinese article, published on July 20, 2025.

Comments NOTHING