I want to pass all my path to index.php?page=path. For example:
domain.com/a/b/c -> index.php?page=a/b/c
Therefore this is my NGINX conf file:
location ~ /(?P<arg1>.*)$ {
fastcgi_pass php:9000;
fastcgi_param QUERY_STRING /index.php?page=$arg1;
}
As far as I know, query string should be everything after .com, right? I'm passing arg1 to it. However, I wanted to ignore truly file paths like /file.jpg
or /images/favicon.ico
. I could simply negate them in regex but then they'd have no path at all.
So how to match /anything
to index.php?page=anything
except for files and actually deliver those files?
You need to use below
location ~ /(.*)$ {
try_files $uri $uri/ /index.php?page=$1;
}
This will first check if file or directory exists if not then pass it to the index.php
file
Based on your Apache's .htaccess, the equivalent setting under Nginx would be:
location / {
# First attempt to serve request as file, then
# as directory, then index.php?page=$args.
try_files $uri $uri/ /index.php?page=$args;
}
I don't know nginx, but assuming truly/real path is something that ends with some kind of extension, and that you can write several rules with top rules having higher priority, you could write 2 rules like these:
First rule matches an url that ends with an extension: ( dot + word ) and does nothing:
/^.*[.]\w+$/
second rule matches anything and captures:
/(.*)/
If that is not possible, you could try to use a rule that matches urls like these: foo/bar/foo/bar/...
(\w+(?:\/\w+)*\/?)
If you don't want to allow last / bar, just use
(\w+(?:\/\w+)*)
The use case you mention is very common, and it's detailed in the common Nginx pitfalls page under the section Front Controller Pattern Web Apps
As per the aforementioned page, for Drupal, Joomla, etc., just use this inside your location block:
try_files $uri $uri/ /index.php?q=$uri&$args;
Since you want to use the "page" variable name, your code will look as follows:
location / {
try_files $uri $uri/ /index.php?page=$uri&args;
}
The part $uri/
is relevant only if you want to serve content from directories, for example if you want to serve a Wordpress blog from yourdomain.com/blog/
. If that's not the case, you can remove the $uri/
part.
My advice is to not use page
as the variable to pass the section/route to PHP, because you might end up having a confusion between which section of the website to show vs. which page number. Page is misleading, I'd use route instead.
Of course, your mileage may vary and you may require something more complex based on your needs, but for basic sites, these will work perfectly. You should always start simple and build from there.
Additionally, to make debugging easier, consider using a verbose error log setting, I'd use info
or notice
to debug routing:
error_log logs/error.log info;
Good luck and keep us posted on how you solved the issue.