PHPの実行方式について調べてみた

## はじめに
PHPでアプリを開発していて、ふとPHPってどのように実行されているのか気になったことはありませんか？PHPのコードはどのように実行されているか実行形式を交えながら見ていきます！

## PHPアプリケーションの処理の概要
まずPHPのアプリケーションの処理の流れを見ていきます。アプリケーションの処理を簡潔に表すと、以下のようになっていて、クライアントからのリクエストをWebサーバーが受け取り、どうにかこうにかPHPを実行した結果をWebサーバーがクライアントにレスポンスとして返します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2435396/821ae833-d485-4559-afc6-5259fe043cfb.png)

今回はそのどうにかこうにかしてPHPを実行するところをより深ぼっていきたいと思います！！

## どうやってPHPは実行されるのか
では実際にどうやってPHPが実行されるのかというお話になるのですが、Webサーバーが関わってきます。

Webサーバー側でプロセスを起動しておき、リクエストが来たらプロセス内でPHPのコードを実行します。
(WebサーバーだとApacheとNginxが有名ですがApacheだとマルチプロセス、つまり複数のプロセスでリクエストを処理しますがNginxはシングルプロセスでリクエストを処理します。)

このプロセス内でPHPは実行されるわけですが、実行方式によってどのプロセスでPHPを実行するかが変わってきます。

## どのような実行方式があるのか
- mod_php
- CGI
- FastCGI
- PHP-FPM

大まかにこの4種類があります。mod_phpはモジュール方式、CGI、FastCGI、PHP-FPMはCGI方式に該当します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2435396/83d22bcb-b85c-4a9e-9332-ee10186603a5.png)

## mod_php
ではここからそれぞれの実行方式について深ぼっていきます。

まずmod_phpですがモジュール方式という実行方式です。これはWebサーバーのApacheで使うことができる実行方式になります。なぜかというとApacheがphpを実行するための拡張モジュールを提供しており、このモジュールを利用して実行するからです。なのでNginxはこの拡張モジュールが存在しないのでモジュール方式も存在しません。

プロセスですが、モジュール方式ではApache内の拡張モジュールを使用するためApache内のプロセスでPHPが実行されます。以下の図でmod_phpではApache内でPHPが実行されていることがわかりますね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2435396/c025c8d2-9b1e-49d6-9263-fa31bb0c9aef.png)
引用：https://www.fumi.org/neta/201205sv.html

#### メリット
- Apacheで実行する際はhttpd.confの設定をいじるだけで簡単にPHPの実行環境が構築できます
- Webサーバー内のプロセスで実行することができるため、実行速度が比較的速いです

#### デメリット
モジュール方式はApache内のプロセスで実行されるため、必然的にApacheの実行権限でPHPファイルを実行することになります。すると例えば複数人で使用しているサーバーの場合、全員がApacheの実行権限でPHPファイルを実行できてしまい、ユーザーごとの実行権限の設定ができないためセキュリティの担保が難しいという問題点があります。

最近だとモジュール方式で実行することは少ないです。実際Redhat(Linuxのディストリビューション)ではモジュール方式でPHPを実行することは非推奨になっています。

https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/8/html/8.7_release_notes/deprecated-functionality_dynamic-programming-languages-web-and-database-servers

## CGI
CGIはWebサーバーの外部プログラムでPHPを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2435396/0f2cd924-7957-427f-bb03-8082d3184ced.png)

引用：https://www.fumi.org/neta/201205sv.html

クライアントからリクエストがあるとWebサーバーの中でphp-cgiという外部プログラムを実行するためのプロセスが起動され、引数や環境変数などを渡してPHPを実行し、結果をWebサーバーがクライアントに返します。

#### メリット
ユーザーごとの権限で実行されるため、他の人のファイルに干渉してしまうというようなセキュリティの問題がないです。

#### デメリット
リクエストごとにPHPを実行するためのプロセスを起動、破棄するため実行する時にメモリを大量に消費してしまい、オーバーヘッドが大きくなります。


## FastCGI
FastCGIはCGIで問題になっているオーバーヘッドを小さくした実行方式になります。
どういうことかというCGIのようにリクエストごとにプロセスを起動するのではなく、事前にプロセスを起動させておく、つまり常駐させておくことでリクエストの処理にプロセスを使い回すことができ、結果的に実行のオーバーヘッドを抑えることができ、処理速度も速くなっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2435396/1a3bf3e9-e8ad-4518-a2e6-4917e41c8a52.png)

引用: https://www.powercms.jp/products/document/developer/server/fastcgi.html

## PHP-FPM
PHP-FPMはFastCGIをPHPで使えるように最適化したものになっています。

Webサーバーにリクエストがくると、FastCGIプロトコル(TCPやUNIXドメインソケット)で通信して、リクエストをPHP-FPMで処理します。PHP-FPMはFastCGI同様にプロセスをいくつか常駐させているため、空いているプロセスで処理をして結果をWebサーバーに返します。
常駐させるプロセス数を設定することができるため、用途に応じて柔軟に対応することができます。

Nginxを使っている場合であればdefault.confに

```
upstream php-fpm {
    server php:9000
}
```

と記載しておけば、9000番ポートで通信をしてPHPの実行ができるようになります。

ちなみにDockerのPHP-FPMのイメージには9000をリッスンするようにデフォルトで設定されています。

https://hub.docker.com/layers/library/php/8.3.20RC1-fpm-alpine3.20/images/sha256-e44ce6c38640df593492d3e14957bff837901c7daa0bbe9fd573013c565c07f3