If you're trying to rewrite clean URLs like /results/summer-meet
to /results/view.php?slug=summer-meet
in Nginx, everything might seem simple... until your .php
files start downloading instead of executing.
Here’s what’s going wrong — and how to fix it.
location ~ ^/(results|standards|meet|heat-sheets|psych-sheets)/ {
try_files $uri $uri/ @rewrite_view;
}
location @rewrite_view {
rewrite ^/(results|standards|meet|heat-sheets|psych-sheets)/([a-z0-9\-]+)$ /$1/view.php?slug=$2 last;
}
Why it fails:
The location ~
block is a regex match.
Nginx gives regex blocks higher priority, and once it matches this block, it does not fallback to your global .php
handler like:
location ~ \.php$ { ... }
Result: /results/view.php
gets matched by the regex block, and since there's no .php
handler inside, Nginx serves it as a static file — or downloads it.
The safest way is to avoid regex and use one location
per folder:
location /results/ {
try_files $uri $uri/ @rewrite_results;
}
location @rewrite_results {
rewrite ^/results/([^/]+)$ /results/view.php?slug=$1 last;
return 404;
}
Repeat for each folder (/standards/
, /meet/
, etc.).
This works because:
location /results/
is a prefix match, not regex
If the file exists (like view.php
), it falls through to the global .php$
handler correctly
No more downloads. Clean, clear routing.
.php
HandlerIf you really want to keep the compact regex style, you must re-define .php
handling for those folders:
location ~ ^/(results|standards|meet|heat-sheets|psych-sheets)/ {
try_files $uri $uri/ @rewrite_view;
}
location ~ ^/(results|standards|meet|heat-sheets|psych-sheets)/.*\.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm-swimsnap.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
This ensures PHP files inside those folders (like view.php
) still get routed through PHP-FPM correctly.
Prefer prefix-based blocks (location /results/
) unless you have a strong reason for regex
If you use location ~
, you must handle .php
within the same scope or via more specific regex
Always verify with nginx -t
and test .php
execution directly to avoid silent errors
If you're seeing downloads or blank responses, chances are it's not your rewrite — it's Nginx falling into the wrong block.