多くの人にとって、Nginx+PHP の構成は、チュートリアルを検索してコピーして貼り付けるだけです。何の問題もないように思えますが、実際には、インターネット上の多くの情報は荒廃しており、抜け穴がたくさんあります。深い理解を求めずにただコピーアンドペーストしていると、遅かれ早かれその代償を払うことになります。
PHP を使用してフロントエンド コントローラーを実装するとします。率直に言えば、これは統合された入口です。すべての PHP リクエストを同じファイルに送信し、それらを解析します。このファイル「REQUEST_URI」はルーティングを実装します。
現時点では、多くのチュートリアルで次のように Nginx+PHP を構成することが説明されています:
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; }}
これには多くのエラーがあります。少なくとも、悪趣味な場所があるので、どれだけ見つけられるか見てみましょう。
まず、Nginx 設定ファイル内の命令の継承関係を理解する必要があります。
Nginx 設定ファイルは、外側から内側まで多くの部分に分かれています。 「server」、「location」などの場合、デフォルトの継承関係は外側から内側です。これは、内側のブロックが外側のブロックの値をデフォルト値として自動的に取得することを意味します。
問題の構成では、「location」で定義されています。
location / { index index.html index.htm index.php;}
新しいデータを将来の「場所」には必ず「インデックス」命令が繰り返し定義されることになります。これは、複数の「場所」が水平関係にあり、継承がないためです。このとき、「インデックス」は「サーバー」で定義する必要があります。継承関係を利用すると、「index」コマンドはすべての「場所」で有効になります。
Nginx のコマンドの中で最も誤解されていると言っても過言ではない
if (!-e $request_filename) { rewrite . /index.php last;}
多くの人がこのコマンドを使用します。 「if」を使用するのが好き この命令は一連のチェックを実行しますが、これは実際には「try_files」命令の責任です:
try_files $uri $uri/ /index.php;
さらに、初心者はよく「if」命令がカーネルレベルの命令ですが、実際には書き換えモジュールの一部であり、Nginx 構成は実際には手続き型ではなく宣言型であるため、非書き換えモジュールからの命令と混合すると、期待どおりの結果が得られない可能性があります。
include fastcgi_params;
Nginx には、「fastcgi_params」と「fastcgi.conf」という 2 つの fastcgi 設定ファイルがあります。これらには大きな違いはありません。唯一の違いは、後者には前者よりも「SCRIPT_FILENAME」定義が 1 行多いことです:
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」が同じレベルで 2 回定義されている場合、両方ともバックエンドに送信されるため、潜在的な問題が発生する可能性があります。このような状況を回避するために、新しい構成ファイルが導入されました。
さらに、セキュリティの問題も考慮する必要があります。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; }}