Suppose we use PHP to implement a front-end controller, or to put it bluntly, a unified entry: send all PHP requests to the same file, and then implement routing by parsing “REQUEST_URI” in this file.
Generally configured like this
At this time, many tutorials will teach you to configure Nginx+PHP like this:
server { listen 80; server_name foo.com; root /path; location / { index index.html index.htm index.php; if (!-e $request_filename) {
rewrite ./index.php last;
}
}
location ~ /.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /path$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
}}
There are a lot of mistakes, or at least bad smells, let’s see if you can find a few.
It is necessary for us to understand the inheritance relationship of the instructions in the Nginx configuration file:
The Nginx configuration file is divided into many blocks. The common ones are “http”, “server”, “location” and so on from the outside to the inside. The default inheritance relationship is from the outside to the inside, that is to say, the inner block will be obtained automatically The value of the outer block is used as the default value.
Let’s start with the “index” directive
In the problem configuration it is defined in “location”:
location / { index index.html index.htm index.php;}
Once a new “location” needs to be added in the future, there will inevitably be repeated “index” instructions. This is because multiple “locations” are in the same level relationship and there is no inheritance. At this time, the “index” should be defined in the “server”. “, with the help of the inheritance relationship, the “index” command can take effect in all “locations”.
Next look at the “if” directive
It is no exaggeration to say that it is the most misunderstood Nginx command:
if (!-e $request_filename) {
rewrite ./index.php last;}
Many people like to use the “if” command to do a series of checks, but this is actually the responsibility of the “try_files” command:
try_files $uri $uri/ /index.php;
In addition, beginners tend to think that the “if” instruction is a kernel-level instruction, but in fact it is part of the rewrite module, and the Nginx configuration is actually declarative rather than procedural, so when it is combined with When instructions from non-rewrite modules are mixed, the result may not be what you want.
Let’s take a look at the “fastcgi_params” configuration file
include fastcgi_params;
Nginx has two fastcgi configuration files, which are “fastcgi_params” and “fastcgi.conf”. There is not much difference between them. The only difference is that the latter has one more definition of “SCRIPT_FILENAME” than the former:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
Note: There is no / between $document_root and $fastcgi_script_name.
Originally, Nginx only had “fastcgi_params”, but later found that many people used hard-coded methods when defining “SCRIPT_FILENAME”, so “fastcgi.conf” was introduced to standardize usage.
But in this case, a question arises: why do we have to introduce a new configuration file instead of modifying the old configuration file? This is because the “fastcgi_param” instruction is an array type, which is the same as ordinary instructions: the inner layer replaces the outer layer; the difference from ordinary instructions is: when used multiple times at the same level, it is added instead of replaced. In other words, if “SCRIPT_FILENAME” is defined twice at the same level, they will both be sent to the backend, which may cause some potential problems. To avoid such situations, a new configuration file is introduced.
In addition, we also need to consider a security issue: when PHP opens “cgi.fix_pathinfo”, PHP may parse the wrong file type as a PHP file. If Nginx and PHP are installed on the same server, then the easiest solution is to use the “try_files” command to do a filter:
try_files $uri =404;
Improved version
According to the previous analysis, an improved version is given, is it much cleaner than the original version:
server { listen 80; server_name foo.com; root /path; index index.html index.htm index.php; location / { try_files $uri $uri/ /index.php$is_args$args;
}
location ~ /.php$ {
try_files $uri =404;
include fastcgi.conf;
fastcgi_pass 127.0.0.1:9000;
}}