Windows10にnginx+PHP環境の構築（初心者の復習用）

#前提条件
- Windows 10 64bit にインストール
- ローカルでの開発用目的

#ダウンロード
##nginxのダウンロード
[nginx公式サイト](http://nginx.org/en/)の[ダウンロードページ](http://nginx.org/en/download.html)の「Stable version（安定版）」の「	nginx/Windows-x.x.x（Windows版）」をダウンロード

##PHPのダウンロード
[PHP公式（Windows用ページ）](http://windows.php.net/)の[ダウンロード](http://windows.php.net/download/)ページから最新バージョンの「Non Thread Safe版」のzipをダウンロード

##「Non Thread Safe」「Thread Safe」の説明
###Non Thread Safe（NTS）
- 「シングルスレッド」環境で動作させるときに使用
- 広範囲に使用されている
- 「FastCGI（Apacheやnginx）」や「CLI（コマンドライン）」など外部アプリとしてPHPを使用するとき

###Thread Safe（TS）
- 「マルチスレッド」環境で動作させるときに使用
- Apacheの内部モジュールでPHPを動かすとき使用（Apacheはマルチスレッドで動作している）


##参考サイト
- [PHP公式の「TS and NTS」の部分](http://windows.php.net/download/)
- [Dr.Clover's Computer Clinic - PHPのスレッドセーフ版(TS)とノンスレッドセーフ版(NTS)の違い](https://mumu.jpn.ph/forest/computer/2017/03/19/8093/)
- [Qiita - 動作中のPHPがZTSかNTSか判定する方法](https://qiita.com/hnw/items/de83634fe39574b76ba1)

#インストール
PHPもnginxもダウンロードしたzipファイルを解凍して好きなディレクトリに移動させる
個人的に下記のディレクトリ構成にしている（PHPもnginxもバージョンを明確にするため敢えてそのままのディレクトリ名）

```
C:\
  └ server\
    ├ htdocs\                         ← ソースファイル
    ├ nginx-1.11.10\                  ← nginxのファイル
    └ php-7.1.11-nts-Win32-VC14-x64\  ← phpのファイル
```

#設定
##nginxの設定
conf/nginx.confを編集してnginxの設定を行う。色々調査して迷ったが下記の設定に自分はしました。

```nginx:conf/nginx.conf
# ワーカープロ説を実行するユーザーの指定
#user  nobody;

# ワーカープロセス（クライアントからリクエストを受け付けて処理するnginxの子プロセス）の数
worker_processes  1;

# プロセスIDを保存するファイルの場所
#pid        logs/nginx.pid;

events {
    # 1ワーカープロセスあたりの最大コネクション数のあたし
    worker_connections  1024;
}

http {
    #### MIMEタイプの設定
    include       mime.types; #拡張子とMIMEタイプの対応ファイルを読み込む
    default_type  application/octet-stream; #拡張子からMIMEタイプを判断できなかった場合のMIMEタイプ

    #### アクセスログの設定
    # アクセスログの書式の設定、main形式を下記の形式で指定
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    # アクセスログの出力場所や書式の指定、main形式でlogs/access.logに出力する
    #access_log  logs/access.log  main;

    #### クライアントへの送信（レスポンス）に関する設定
    # クライアントへの送信にsendfileシステムコールを使うか
    sendfile        on;
    # LinuxのTCP_CORKソケットオプションを使用するか
    #tcp_nopush     on;

    # keepaliveのタイムアウト時間の設定、65秒
    keepalive_timeout  65;

    # クライアントにコンテンツを送信する際に圧縮転送するかどうかの設定
    #gzip  on;

    #### バーチャルサーバーの設定
    server {
        #### サーバーの基本設定
        # リクエストを受け付けるIPアドレスやポート番号を設定
        listen       80;
        # バーチャルサーバーのホスト名を設定
        server_name  localhost;
        # rootドキュメントを指定、windowsでも「\」ではなく「/」でディレクトリ階層を指定
        root   C:/server/htdocs/testProject/public;
        # indexファイル名を設定、
        # URLが「/」で終わってるものに対してインデックスとして使われるファイル名の指定
        index  index.php index.html index.htm;  #前から順番に適用される

        #### サーバー別のログの設定
        # アクセスログの出力先と出力形式の設定、main形式で出力
        access_log  logs/access.log  main;
        # エラーログの出力先とロギングレベルの設定、noticeレベルまで出力
        error_log  logs/error.log  notice;

        #### エラーページの設定
        #error_page  404              /404.html;
        error_page   500 502 503 504  /50x.html; #エラーページのパスを設定
        location = /50x.html { #「/50x.html」にパスが完全一致、一致したら切り上げ
            root   html;
        }

        #### PHPの設定
        # 正規表現、パスが「xxxx.php」や「aaa/xxxx.php」や「abc/xxxx.php/bbbb」などに一致
        location ~ [^/]\.php(/|$) {
            # $fastcgi_path_info の値をキャプチャする正規表現を定義
            # 一つ目の()が $fastcgi_script_name の値になり、二つ目は $fastcgi_path_info の値になる
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;

            # $document_root ルートディレクトリで設定したパス
            # $fastcgi_script_name ファイル名のパス
            # -f はファイルが存在するかの判定
            # ファイルがなければ404エラーを返す
            if (!-f $document_root$fastcgi_script_name) {
                return 404;
            }

            # phpへアクセスするためのIPアドレスとポートの設定
            fastcgi_pass   127.0.0.1:9000;
            # phpでのindexファイル名を設定、
            # URLが「/」で終わってるものに対してインデックスとして使われるファイル名の指定
            fastcgi_index  index.php;

            #### fastcgi_param に関する設定
            # 多数のfastcgi_paramsの設定が書いてあるfastcgi_paramsファイルを読み込む
            include        fastcgi_params;
            # 「HTTP_PROXY」パラメータを空にする、HTTPoxyに関する脆弱性を和らげる
            fastcgi_param  HTTP_PROXY "";
            # 「SCRIPT_FILENAME」パラメータはphp-fpmがスクリプト名を決定するための設定
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        }
    }
}
```
##phpの設定
phpディレクトリ直下の「php.ini-development」をコピー＆ペーストして「php.ini」に名前変更してphp.iniを作成（開発ように使う場合）

##参考サイト
- [nginx公式 - PHP FastCGI Example](https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/)
- [nginx公式 - Module ngx_http_fastcgi_module](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_index)
- [Qiita - nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する](https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc)
- [Qiita - nginx $document_root$fastcgi_script_name と $request_filename の違い](https://qiita.com/kotarella1110/items/3b0bd84fdb55276f37d9)

#起動
##nginxの起動
コマンドプロンプトでnginxのディレクトリ（nginx.exeがある場所）に移動して下記のコマンドを実行

```
START nginx.exe
```
- START ・・・指定したコマンドを新しい環境で新規に開始する（新規コマンドウインドウが開かれてnginxが実行されるがコマンドが終了したら閉じられる、nginx.exeだけ実行するとプロンプトが固まる）

##php-cgiの起動
PHPをインストールしたディレクトリ（php-cgi.exeがある場所）で下記のコマンドを実行

```
START php-cgi.exe -b 127.0.0.1:9000
```
- START ・・・PHPの方は新規ウインドウ開いたまま、php-cgi.exeだけ実行するとプロンプトが固まる）
- -b ・・・FastCGIモード時のバインドパス、このIPにアクセスしたらPHPにアクセスできる

##.batファイル
下記のような.batファイルを用意するとワンクリックで開始できる

```bat:start-nginx.bat
@ECHO off
REM REMはコメントです
REM ECHO off は、これ以降のコマンド全ての実行結果を表示させない
REM @をコマンドの頭に付けると、そのコマンドの実行結果を表示させない

CD C:\server\nginx-1.11.10
REM nginxを起動
START nginx.exe

CD C:\server\php-7.1.11-nts-Win32-VC14-x64
REM phpを起動
REM -bはFastCGIモード時のバインドパス指定、nginxの設定ファイル（nginx.conf）のfastcgi_pass の値を設定
START php-cgi.exe -b 127.0.0.1:9000

EXIT
```

※「START nginx.exe」は「START C:\server\php-7.1.11-nts-Win32-VC14-x64\nginx.exe」の絶対パスだと失敗する。nginxは起動時に「logs」ディレクトリに「nginx.pid」というファイルを作成するのだが、絶対パス指定だとこれの作成に失敗してnginxの起動にも失敗している模様。

#終了
##nginxの終了
コマンドプロンプトでnginxのディレクトリ（nginx.exeファイルがある場所）に移動して下記のどちらかのnginxコマンドを入力

###リクエスト処理後に停止

```
nginx.exe -s quit 
```

###強制停止

```
nginx.exe -s stop
```

##php-cgiの終了
コマンドプロンプトの下記コマンドで終了

```
Taskkill /im php-cgi.exe
```
- Taskkill・・・コンピューター上で実行されているプロセスを終了
- /im・・・終了対象となるプロセスのイメージ名を指定

###.batファイル
下記のような.batファイルを用意するとワンクリックで終了できる

```bat:stop-nginx.bat
@ECHO off

CD C:\server\nginx-1.11.10
REM nginxのコマンドで終了
nginx.exe -s quit

REM phpを終了させる
REM taskkill コンピューター上で実行されているプロセスを終了
REM /im 終了対象となるプロセスのイメージ名を指定
Taskkill /im php-cgi.exe

EXIT
```

※「nginx.exe -s quit」は「C:\server\nginx-1.11.10\nginx.exe -s quit」の絶対パスだと失敗する。nginxは終了時に「logs」ディレクトリに「nginx.pid」というファイルを削除するのだが、絶対パス指定だとこれの作成削除に失敗してnginxの終了にも失敗している模様。