🪟

Windows ServerにScoopでPHPを入れてIISで動かす

2023/04/15に公開

Scoop + PHP + IIS (Windows Server) メモ。

はじめに

ローカル環境内の Windows Server + IIS で PHP を動作させました。できるだけバージョンアップ管理がしやすい環境にしたいと考えました。

Scoop を使って PHP のインストールができたので、手順を残しておきます。

少し補足

この用途なら Scoop よりも Chocolatey のほうがいいかもしれませんが、私は Chocolatey を使用していないため、Scoop で PHP をインストールすることとします。

Scoop で試したら上手くいったので、一旦この手順を記しておきます。

環境

  • Windows Server 2022
  • IIS Version 10 (既にインストール済みとします)
  • Scoop v0.3.1 (Released at 2022-11-15)

Scoop で入れるもの

  • sudo (管理者モードで PowerShell を起動する場合は不要)
  • php-nts
    • 古いバージョンの場合は phpbucket のphp*.*-nts (後述)

php-ntsとは Non Thread Safe 版のことです。Microsoft の公式ドキュメントでは、IIS での使用には Non Thread Safe 版が推奨されています。実際はどちらでも OK のようですが、IIS+FastCGI ではパフォーマンスの理由により Non Thread Safe 版を推奨しているようです。

https://learn.microsoft.com/ja-jp/iis/application-frameworks/install-and-configure-php-on-iis/install-and-configure-php
https://www.ipentec.com/document/php-thread-safe-nonthread-safe-difference

Scoop 本体のインストール

まずは Scoop 本体のインストール

Scoop 公式サイトにあるように PowerShell で下記の通りに実行

PS> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
PS> irm get.scoop.sh | iex

すると、C:\Users\ユーザ名\scoopにインストールされます。PATH環境変数にC:\Users\ユーザ名\scoop\shimsが追加されるので、scoop コマンドが使えるようになります。

(PATH環境変数が反映されない場合は、一旦 PowerShell を再起動したほうがいいかも)

PHP インストール時の手順

おなじみsudoを入れます。管理者モードで PowerShell を使用する場合は不要です。

PS> scoop install sudo

続いてphp-ntsを入れます。

ここでは--globalを付けてインストールします。

PS> sudo scoop install --global php-nts

--globalオプションをつけると、グローバル領域C:\ProgramData\scoop\apps\にインストールされます。そのためにsudoもしくは管理者モードの PowerShell が必要でした。(管理者モードで PowerShell を起動している場合、先頭のsudoは不要です。この後のものも全て同様)

2023 年 4 月時点では PHP 8.2.5 がインストールされます。

PS> php -v
PHP 8.2.5 (cli) (built: Apr 12 2023 08:42:33) (NTS Visual C++ 2019 x64)
Copyright (c) The PHP Group
Zend Engine v4.2.5, Copyright (c) Zend Technologies

scoop hold で PHP のバージョン固定

IIS 起動中(php-cgi.exe プロセスが実行中)に PHP をバージョンアップしようすると、おそらく失敗します。

なのでバージョンを固定しておきます。

PS> sudo scoop hold --global php-nts

IIS に PHP を設定

C:\ProgramData\scoop\apps\php-nts\current\に php-cgi.exe がインストールされていますので、IIS のハンドラーマッピングに追加します。
C:\ProgramData\scoop\apps\php-nts\current\はインストールしたバージョンへのリンクになっています。

PS> sudo Add-WebConfiguration "/system.Webserver/fastcgi" -Value @{fullPath="C:\ProgramData\scoop\apps\php-nts\current\php-cgi.exe"}
PS> sudo New-WebHandler -Name "PHP" -Path "*.php" -Verb "*" -Modules "FastCgiModule" -ScriptProcessor "C:\ProgramData\scoop\apps\php-nts\current\php-cgi.exe" -ResourceType File

New-WebHandlerというコマンドは初めて使いましたが、便利ですね。

GUI でハンドラーマッピングを設定したい場合は、こちらのサイトを参考にしてみてください。
https://www.ipentec.com/document/windows-windows-server-install-php

動作確認

IIS の DocumentRoot 内に phpinfo.php ファイルを設置し内容は下記のようにします。

phpinfo.php
<?php
phpinfo();

ブラウザから phpinfo.php へアクセスして動作確認してください。

php.ini と PHP_INI_SCAN_DIR 環境変数

Scoop でグローバル領域に PHP をインストールするとC:\ProgramData\scoop\persist\php-nts\cli\php.iniに php.ini-production の内容がコピーされます。

Scoop で PHP をインストールするとPHP_INI_SCAN_DIR環境変数が自動的に設定されます。その内容はこうなっています。

  • C:\ProgramData\scoop\apps\php-nts\current\cli\
  • C:\ProgramData\scoop\apps\php-nts\current\cli\conf.d\

これらのディレクトリへ*.ini ファイルを設置すれば追加で読み込まれます。

C:\ProgramData\scoop\apps\php-nts\current\cli\C:\ProgramData\scoop\persist\php-nts\cli\へのリンク(ジャンクション)になっています。

C:\ProgramData\scoop\persist\内のファイルは Scoop のパッケージをバージョンアップしても変更されることが無いので、この php.ini を直接編集しても大丈夫ですが、私はC:\ProgramData\scoop\persist\php-nts\current\cli\conf.d\に追加でphp-additional.iniという名前で追加の ini ファイルを設置しました。

一例として、extension を追加したい場合はこのように記述します。

php-additional.ini
extension=php_curl.dll
extension=php_gd.dll
extension=php_mbstring.dll

; などなど…

PHP の INI ファイルを追加 or 変更したら IIS を再起動します。

PS> sudo iisreset /restart

PHP バージョンアップ

scoop holdでバージョンを固定したので、そのままではバージョンアップできないようになっています。(通常はscoop updatesudo scoop update --global *で全てのグローバルにインストールしたパッケージがアップデートされます。)

先程も述べましたが、IIS 起動中(php-cgi.exe プロセスが実行中)に PHP をバージョンアップしないほうがいいと思われますので、IIS を停止させます。

IIS の停止とバージョンアップ手順

まずは IIS を停止します。

PS> sudo iisreset /stop

scoop unholdでバージョン固定を解除します

PS> sudo scoop unhold --global php-nts

PHP をアップデート

# 本体とパッケージ一覧の更新
PS> scoop update
# php-ntsパッケージの更新
PS> sudo scoop update --global php-nts

IIS を再び起動し、正しくバージョンアップしているか確認します。

PS> sudo iisreset /start

再びバージョンを固定しておきます。

PS> sudo scoop hold --global php-nts

バージョンを戻す

例えば PHP 8.2.4 がインストールされているならば、このバージョンに戻すこともできます。

PS> sudo iisreset /stop
PS> sudo scoop reset php-nts@8.2.4
PS> sudo iisreset /start

古いバージョンをインストールする場合

Scoop には bucket という(Homebrew のbrew tapのような)概念があり、外部のパッケージリポジトリを追加することができます。

Scoop で PHP の古いバージョンをインストールする場合、通常はversionsbucket を追加するところですが、versionsbucket では Non Thread Safe 版のパッケージは無いようです。

代わりにphpbucket には Non Thread Safe 版のパッケージがあります。パッケージ名の末尾に-ntsと付いているものです。

ここでは PHP 7.1.4(nts)をインストールしてみます。

例: PHP 7.1.4(nts)のインストール

まずはphpbucket を追加します。

PS> scoop bucket add php

IIS を停止し、現在インストールされている PHP をアンインストールしておきます。

PS> sudo iisreset /stop
PS> sudo scoop uninstall --global php-nts

PHP 7.1.4(nts)をインストールします

PS> sudo scoop install --global php7.1.4-nts

IIS の PHP ハンドラーマッピングを作り直します。

PS> sudo Clear-WebConfiguration -Filter "/system.Webserver/fastcgi/application"
PS> sudo Remove-WebHandler -Name "PHP"

PS> sudo Add-WebConfiguration "/system.Webserver/fastcgi" -Value @{fullPath="C:\ProgramData\scoop\apps\php7.1.4-nts\current\php-cgi.exe"}
PS> sudo New-WebHandler -Name "PHP" -Path "*.php" -Verb "*" -Modules "FastCgiModule" -ScriptProcessor "C:\ProgramData\scoop\apps\php7.1.4-nts\current\php-cgi.exe" -ResourceType File

IIS を再び起動し、古いバージョンが動作しているか確認します。

PS> sudo iisreset /start

phpbucket の php.ini

mainbucket の php-nts とは違い、php.ini はC:\ProgramData\scoop\apps\php7.1.4-nts\current\php.iniにあるようです。内容は php.ini-production のようです。

PHP_INI_SCAN_DIR環境変数はC:\ProgramData\scoop\persist\php7.1.4-nts\current\conf.d\に指定されているので、こちらに追加の設定 INI ファイルを設置するようにしてみます。

この内容は先述の php-nts の php-additional.ini と変わりないので省略します。

PHP の INI ファイルを変更したら IIS を再起動します。

PS> sudo iisreset /restart

おしまい

sudoだらけになってしまいました。これなら管理者モードで PowerShell を使ったほうがいいかもしれませんが、一応念の為、通常モードの PowerShell で作業しています。

冒頭でも触れましたが、私は Chocolatey について詳しくはないですが、おそらく同じような感じかと思います。多分……。もしかしたら Chocolatey のほうがいいかもしれませんね。

Discussion