Nginx+PHP configuration

Suppose we use PHP to implement a front 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.

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 many mistakes, or at least bad smells, you can find a few if you look at them.

It is necessary for us to first understand the inheritance relationship of the directives in the Nginx configuration file:

The Nginx configuration file is divided into many blocks. The common ones are "http", "server", "location", etc. from the outside to the inside. The default inheritance relationship is from the outside to the inside, which means that the inner block will be automatically obtained The value of the outer block is taken as the default value.

Let's start with the "index" command first

It is defined in "location" in the problem configuration:

location / {
    index index.html index.htm index.php;
}

Once a new "location" needs to be added in the future, there will inevitably be a repeatedly defined "index" command. This is because multiple "locations" are in a level relationship and there is no inheritance. At this time, the "index" should be defined in the "server" ", with the help of inheritance, the "index" command can take effect in all "locations".

Next look at the "if" command

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 often 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 the instructions of 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, namely "fastcgi_params" and "fastcgi.conf". They are not much different. The only difference is that the latter has an extra line of "SCRIPT_FILENAME" definition than the former:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

注意:$document_root 和 $fastcgi_script_name 之间没有 /。

原本Nginx只有「fastcgi_params」,后来发现很多人在定义「SCRIPT_FILENAME」时使用了硬编码的方式,于是为了规范用法便引入了「fastcgi.conf」。

不过这样的话就产生一个疑问:为什么一定要引入一个新的配置文件,而不是修改旧的配置文件?这是因为「fastcgi_param」指令是数组型的,和普通指令相同的是:内层替换外层;和普通指令不同的是:当在同级多次使用的时候,是新增而不是替换。换句话说,如果在同级定义两次「SCRIPT_FILENAME」,那么它们都会被发送到后端,这可能会导致一些潜在的问题,为了避免此类情况,便引入了一个新的配置文件。

此外,我们还需要考虑一个安全问题:在PHP开启「cgi.fix_pathinfo」的情况下,PHP可能会把错误的文件类型当作PHP文件来解析。如果Nginx和PHP安装在同一台服务器上的话,那么最简单的解决方法是用「try_files」指令做一次过滤:

try_files $uri =404;
依照前面的分析,给出一份改良后的版本,是不是比开始的版本清爽了很多:
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;
    }
}
更过技术问题解决防范请搜索千锋PHP,千锋论坛

Guess you like

Origin blog.csdn.net/chengshaolei2012/article/details/72638576