PHP 7.3をビルドしてApacheと連携させる

ビルドした PHP 7.3 を Apache と連携させたいと思いました。

# 概要
## 環境
- CentOS 7.6.1810
  - 以前 Vagrant + Ansible で構築した環境です。
  - 詳しくは [Vagrant+AnsibleでPHPのビルド環境を作る](https://qiita.com/aminevsky/items/af37ba135239b30aa016) を参照。

## やりたいこと
- PHP でセッションの動作を確認したい。
  - PHP と Apache を連携させないといけない。

## やること
- Apache 2.4.6 をインストールします。
  - 面倒なのでビルドせずに `yum` でインストールします（汗）
- PHP 7.3 をビルドします。
  - 将来的にデバッグしながら動かしてみたいので、あえてビルドします。
  - 最新の開発版には Apache が対応していないので、おとなしく 7.3 にします。[^1]

[^1]: 最新の開発版では PHP のバージョンが 8 になっています。その影響で `libs/libphp8.so` となっているのですが、これでは Apache が認識してくれません。

# 手順
## Apacheをインストールする

`yum` で Apache をインストールします。
`apxs` というツールが必要なので `httpd-devel` もインストールします。

```console
$ sudo yum install httpd httpd-devel
```

念のため、いろいろ確認しておきましょう。
`apxs` のパスは PHP をビルドするときに必要になるのでメモしておきます。

```console
$ ls /etc/httpd/
conf  conf.d  conf.modules.d  logs  modules  run
```

```console
$ which apachectl
/usr/sbin/apachectl

$ which apxs
/usr/bin/apxs
```

ちなみに、`apxs` の説明は以下のとおりです（`man apxs`）。

> apxs is a tool for building and installing extension modules for the Apache HyperText Transfer Protocol (HTTP) server. This is achieved by  building a dynamic shared object (DSO) from one or more source or object files which then can be loaded into the Apache server under runtime via the LoadModule directive from mod_so.

これを使うと、モジュールを追加するたびに Apache をビルドしなおさずに済み、`httpd.conf` に `LoadModule` を追加するだけでモジュールを追加できるようになるということらしいですね。

デフォルトの `DocumentRoot` は `/var/www/html` ですが、所有者とパーミッションを変更しておきます。[^2]

[^2]: ローカル環境なのでこうしましたが、本番環境ではちゃんと検討したほうがいいです、うん。

```console
$ sudo chown apache:apache /var/www/html
$ sudo chmod 777 /var/www/html
```

## PHPをインストールする

まずは [GitHub](https://github.com/php/php-src) からソースコードを取得します。
今回は PHP 7.3 を使いたいので、ブランチを指定してチェックアウトします。

```console
$ git clone https://github.com/php/php-src.git
$ git checkout -b PHP-7.3 remotes/origin/PHP-7.3
```

PHP をビルドします。
`configure` で `apxs` のパスを指定するところが重要です。[^3]

[^3]: `--enable-debug` はデバッグを有効にするオプションです。`--with-config-file-path` は `php.ini` の検索場所を指定するオプションで、複数バージョンを共存させたいので、あえて指定しています。

```console
$ cd php-src
$ ./buildconf
$ ./configure --enable-debug --with-apxs2=/usr/bin/apxs --with-config-file-path=/home/vagrant/php7/
$ make
```

通常は `make install` するところですが、複数バージョンを共存させたいので、あえてしません。
ただ、このままでは `libphp7.so` が Apache のディレクトリにコピーされません。
ということで、シンボリックリンクを作成しておきます。

```console
cd /etc/httpd/modules/
sudo ln -s ~/php-src/libs/libphp7.so libphp7.so
```

## Apacheを設定する

`/etc/httpd/conf/httpd.conf` に以下を追加します。

```
LoadModule php7_module modules/libphp7.so

<FilesMatch \.php$>
     SetHandler application/x-httpd-php
</FilesMatch>
```

追加したら、Apache を再起動します。

```
apachectl stop
apachectl start
```

## チェックする

まずは、`phpinfo()` を表示するだけの PHP ファイルを `/var/www/html` に作成します。
ブラウザーでアクセスすると、以下のように表示されるはずです。

<img width="976" alt="スクリーンショット 2019-03-03 12.17.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/141299/a53ba29d-8ac5-738c-6a3f-d5ee3ac15861.png">


# ちなみに・・・

もともとやりたかったことは **PHP でセッションの動作を確認する** ことでした。

ということで、以下のような PHP ファイルを作成しました。

```php
<?php
session_start();
$_SESSION['hoge'] = 'foo';
```

ブラウザーで PHP ファイルにアクセスすると、どこかにセッションファイルが作成されているはずです。
セッションファイルには **セッション ID** が含まれています。

セッション ID は Cookie に格納されているので、ブラウザーの開発者ツールで確認することができます。
例えば、Firefox では以下のように、「開発ツール」の「ストレージ」で確認できます。

<img width="1274" alt="スクリーンショット 2019-03-03 12.26.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/141299/e8c084f7-be7a-06ed-df64-a102dcd1a5a3.png">

セッション ID がわかったので、`find` コマンドで検索します。

```console
$ sudo find / -name "*9d589ed8928566f911d*" 2>/dev/null
/tmp/systemd-private-40934c4f7fd945a5b989da2b7141f6de-httpd.service-czqFF3/tmp/sess_9d589ed8928566f911def19013b983f7
```

なんだかクソ長いファイル名がヒットしましたが、デフォルトでは `/tmp` の配下に保存されるようですね。
中身を確認すると、たしかにセッションが保存されています。

```console
$ sudo cat /tmp/systemd-private-40934c4f7fd945a5b989da2b7141f6de-httpd.service-czqFF3/tmp/sess_9d589ed8928566f911def19013b983f7
hoge|s:3:"foo";
```

ところで、この長いファイル名は何なのでしょうか・・・
調べてみると、`systemd` の PrivateTmp が有効になっているかららしいですね。

もっとも `/tmp` をセッションファイルの保存先にするのは通常はないでしょう。

ということで便宜的に `/var/www/sessions` ディレクトリを作ります。

```console
$ sudo mkdir /var/www/sessions
$ sudo chown -R apache:apache /var/www/sessions
```

そして、`php.ini` を編集して `/var/www/sessions` ディレクトリに書き込むように、`session.save_path` を変更します。

```
session.save_path = "/var/www/sessions"
```

最後に、Apache を再起動します。

```console
sudo apachectl restart
```

再びブラウザーでアクセスすると、以下のように `/var/www/sessions` ディレクトリにセッションファイルが作成されているはずです。
`sess_` の後ろの部分がセッション ID になっています。

```console
$ ls -lt /var/www/sessions/
total 4
-rw-------. 1 apache apache 15  3月  3 13:30 sess_hck9fsfqbtvg47elrkia6iv50n
```

# 参考
- PHP マニュアル
    - Unix システムへのインストール
        - [Apache 2.x (Unixシステム用)](http://php.net/manual/ja/install.unix.apache2.php)
    - [中心となる configure オプションのリスト](http://php.net/manual/ja/configure.about.php)

- [CentOS7のhttpdはそのままだと（mod_php経由などで） /tmpに書き込もうとすると実は別のディレクトリに書き込まれる](https://qiita.com/k1LoW/items/50017db5e66f87051afd)