更新が止まった(?)XAMPPに新バージョンのPHPを導入する

### 前書き

2023年11月に`Ver.8.2.12`となって以来、更新が止まってしまったように見える`XAMPP`に、
新たな`PHP8.3.10`を追加導入した時に苦労した点をまとめました。

:::note info
PHP8.3.11 がリリースされたので、
ここ以降の`PHP8.3.10`の部分は`PHP8.3.xxx`に変更しました。
:::

現在すでに`PHP8.4`~~アルファ版~~（「ベータ版」が公開されました）が公開されているというのに、`8.3`のリリースが無いのはどうしたことでしょう？
なお、今後 XAMPP の更新が無くなってしまった場合、新たな PHPテスト環境を探す必要が出てくるかもしれません。

Mac では`ServBay`(macOS 12.0 Monterey/それ以降限定)という PHPテスト環境が使えるようです。
Windows ではどうなるのでしょうか？

ここでは、いい方法が見つかるまでのつなぎとして、
従来の`XAMPP`に新しいバージョンの`PHP`を導入した時の注意事項などを書いています。

:::note info

私の環境
+ Windows 10 Home（22H2）
+ Dドライブに`XAMPP for Windows`をインストールしています。
+ shie-works(no shi)さんの[xamppで複数のバージョンのphpを切り替えて使いたい！！！](https://qiita.com/shie-works/items/65234ffb6753e277d621 "xamppで複数のバージョンのphpを切り替えて使いたい！！！")を導入しています。
+ Webサーバーとして、XAMPP付属のApacheを利用しています。
+ XAMPP の最新バージョン XAMPP8.2.12 をインストールしてる状況での記事となります。

これと異なる環境の方は、それぞれの環境に合わせて読み替えて下さい。

:::

:::note warn

「複数バージョンの切替」をしていない `XAMPP8.2.12` を単独で使用している方が、「PHP のバージョンアップだけしたい！（切替はやらない）」という場合は、この後の、[1]で従来の`php`フォルダを別のフォルダ名`php8_2_12`など）にリネームしてバックアップしつつ、ダウンロード・展開してできたフォルダを新しい`php`フォルダとし、[2][3][4][7]は飛ばして~~いただけばいいのでは？~~（訂正：いただいても`PHP8.3`として動いてくれるのでは） ...と思います。

`PHP8.3`として動いているかどうかは、
```PHP
phpinfo();
```
で確認できます。

もし何かあれば情報ください。あるいは別記事書かれた場合は、このページからのリンクを書かせていただきたいかもです。

:::

:::note warn

`PHP8.3`では、
> PHP の実行をサポートする Windows の最低バージョンが、Windows 8 と Windows Server 2012 になりました。

とされています。従って、これら以降のマシン上でなければ、`PHP8.3`を動かすことはできないみたいです。

:::

### 作業前のツリー構造（一部省略）

```

D:
├─xampp
│  ├─apache
│  │  └─conf
│  │      └─extra
│  │            httpd-xampp8_2_12.conf
│  ...
├─xampp8_2_12
│  ├─php
│  │  │  php.ini
│  │  └─extras
│  │        browscap.ini
│  ...

```

## [1] 新しいバージョンのPHPを入手する
(1) [PHPマニュアルのページ](https://www.php.net/manual/ja/ "PHPマニュアルのページ")から、「Downloads」をクリックします。
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327025/f6ed252f-2b82-afb9-3362-c11b8f21d49d.jpeg)

(2) Downloads ページから、「Windows downloads」をクリックします。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327025/acfbe03b-b90e-61cb-127f-5894f82e6955.jpeg)

(3) 表示されたページから、「VS16 **x64 Thread Safe** ...」の「**Zip**」をクリックします。
![PHP8.3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327025/ff7a0317-d9e8-a250-ef3d-8ad3c3d0be4e.jpeg)


:::note warn
**注意**
「x64」は、コンピュータの`CPU`のタイプ（だと思います）。
64bitパソコンなら、全部これでいいんじゃないのかな？...
32bitパソコンなら、「x86」になると思います。...
→ もし違ってたら教えてください。

「Thread Safe」は、`Apache`を使う場合はこれでなければならないようです。上の画像の左側=赤線部分=に、

> **With Apache, using the apache2handler SAPI, you have to use the Thread Safe (TS) versions of PHP.**

と書かれています。`XAMPP`は通常、Webサーバーとして`Apache`を使います。（私の環境でも`Apache`を利用しています。）
:::

:::note alert
**警告**
ダウンロードすべきリンクは、絶対に押し間違えないでください。
私はここで間違えました。大変な時間をロスしました。

「**VS16 x64** ...」で始まっていても、
「**VS16 x64 Thread Safe** ...」　　 （←○）
「**VS16 x64 Non Thread Safe** ...」（←Ｘ）
の2種類あります。
紛らわしいので注意してください。
:::

### (4) ハッシュ値（sha256）を確認
ダウンロード間違いが無いか、ハッシュ値（sha256）を確認します。
`HashSum`のようなフリーソフトか、PHPでも
```PHP
echo hash_file('sha256', 'ダウンロードしたファイルのパス');
```
で確認できます。ダウンロードしたページに書かれている...
```
92ac126ead07bc1fb14832d83bb9020144399d0f33ea1cc537b1c8c5c8c61a00
```
（PHP8.3.10 以外はダウンロードページのものと照合してください。）になっていればOKです。心配な人は、さらにウイルスチェックもしましょう。私はノートン360でウイルスチェックしました。

### (5) ダウンロードしたファイルを展開し、`xampp`フォルダ下に移動
ダウンロードした`php-8.3.xxx-Win32-vs16-x64.zip`ファイルを**展開**し、できたフォルダの名前を
「**PHP8_3_xxx**」にリネームし、
`D:\xampp`フォルダ下に移動します。

（なお、このフォルダはこの後いくつかの修正を施した後、[7]で「`D:\xampp8_3_xxx\php`」フォルダとしてコピーされます。）

```
（現在のツリー構造）
D:
├─xampp
│  ├─php8_3_xxx------------------------[1]
│  ├─apache
│  │  └─conf
│  │      └─extra
│  │            httpd-xampp8_2_12.conf
│  ...
├─xampp8_2_12
│  ...
```

## [2] httpd-xampp8_3_xxx.conf ファイル

「`D:\xampp\apache\conf\extra\httpd-xampp8_2_12.conf`」を同じフォルダにコピーし、
「httpd-xampp`8_3_xxx`.conf」にリネームし、
さらに、
そのファイル内の「**8_2_12**」と記述されている部分をすべて、「**8_3_xxx**」に書き換えて上書き保存します。


<details><summary>この時点のツリー構造が見たい方はこちら</summary>

```
（現在のツリー構造）
D:
├─xampp
│  ├─php8_3_xxx------------------------[1]
│  ├─apache
│  │  └─conf
│  │      └─extra
│  │            httpd-xampp8_2_12.conf-----[2]
│  │            httpd-xampp8_3_xxx.conf----[2]
│  ...
├─xampp8_2_12
│  ...
```

</details>

## [3] xampp8_3_xxx フォルダ
`D:\xampp8_2_12`フォルダを同じ場所にコピーし、`xampp8_3_xxx`にリネームする。


<details><summary>この時点のツリー構造が見たい方はこちら</summary>

```
（現在のツリー構造）
D:
├─xampp
│  ├─php8_3_xxx------------------------[1]
│  ├─apache
│  │  └─conf
│  │      └─extra
│  │            httpd-xampp8_2_12.conf-----[2]
│  │            httpd-xampp8_3_xxx.conf----[2]
│  ...
├─xampp8_2_12---------------------------------[3]
└─xampp8_3_xxx--------------------------------[3]
    ├─apache
    │  └─conf
    │      │  httpd.conf
    │      └─extra
    │             httpd-autoindex.conf
    │             httpd-dav.conf
    │             httpd-manual.conf
    │             httpd-multilang-errordoc.conf
    │             httpd-ssl.conf
 ```

</details>

## [4] xampp8_3_xxx フォルダ内のconfファイル
下記のファイル内の「**8_2_12**」と記述されている部分をすべて、「**8_3_xxx**」に書き換えて上書き保存する。（テキストエディタの「置換」機能を利用します。）

+ D:\xampp8_3_xxx\apache\conf\httpd.conf
+ D:\xampp8_3_xxx\apache\conf\extra\httpd-autoindex.conf
+ D:\xampp8_3_xxx\apache\conf\extra\httpd-dav.conf
+ D:\xampp8_3_xxx\apache\conf\extra\httpd-manual.conf
+ D:\xampp8_3_xxx\apache\conf\extra\httpd-multilang-errordoc.conf
+ D:\xampp8_3_xxx\apache\conf\extra\httpd-ssl.conf

<details><summary>この時点のツリー構造が見たい方はこちら</summary>

```
（現在のツリー構造）
D:
├─xampp
│  ├─php8_3_xxx------------------------[1]
│  │      php.ini-development
│  ├─apache
│  │  └─conf
│  │      └─extra
│  │            httpd-xampp8_2_12.conf-----[2]
│  │            httpd-xampp8_3_xxx.conf----[2]
│  ...
├─xampp8_2_12---------------------------------[3]
│  ├─php
│  │      php.ini
│  ...
└─xampp8_3_xxx--------------------------------[3]
    ├─apache
    │  └─conf
    │      │  httpd.conf-------------------------[4]
    │      └─extra
    │             httpd-autoindex.conf------------[4]
    │             httpd-dav.conf------------------[4]
    │             httpd-manual.conf---------------[4]
    │             httpd-multilang-errordoc.conf---[4]
    │             httpd-ssl.conf------------------[4]
```

</details>

## [5] php.ini
`D:\xampp\php8_3_xxx\php.ini-development`を同じフォルダ内にコピーし、`php.ini`にリネームする。

なお、従来の設定は　`D:\xampp8_2_12\php\php.ini`に書かれている通りなので、
それを参考にしつつ、`D:\xampp\php8_3_xxx\php.ini`を編集する。


<details><summary>この時点のツリー構造が見たい方はこちら</summary>

```
（現在のツリー構造）
D:
├─xampp
│  ├─php8_3_xxx------------------------[1]
│  │  │  php.ini-development-----------------------[5]
│  │  │  php.ini-----------------------------------[5]
│  │  └─extras
│  ├─apache
│  │  └─conf
│  │      └─extra
│  │            httpd-xampp8_2_12.conf-----[2]
│  │            httpd-xampp8_3_xxx.conf----[2]
│  ...
├─xampp8_2_12---------------------------------[3]
│  ├─php
│  │      php.ini-----------------------------------[5]
│  ...
└─xampp8_3_xxx--------------------------------[3]
    ├─apache
    │  └─conf
    │      │  httpd.conf-------------------------[4]
    │      └─extra
    │             httpd-autoindex.conf------------[4]
    │             httpd-dav.conf------------------[4]
    │             httpd-manual.conf---------------[4]
    │             httpd-multilang-errordoc.conf---[4]
    │             httpd-ssl.conf------------------[4]
```

</details>

<details><summary>私のテスト環境での php.ini の内容を見たい方は、こちら。（コメント行は削除しています。）</summary>

```ini
[PHP]

;;;;;;;;;;;;;;;;;;;
; About php.ini   ;
;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;
; About this file ;
;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;
; Quick Reference ;
;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;
; Language Options ;
;;;;;;;;;;;;;;;;;;;;

engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
zend.exception_ignore_args = Off
zend.exception_string_param_max_len = 15

;;;;;;;;;;;;;;;;;
; Miscellaneous ;
;;;;;;;;;;;;;;;;;

expose_php = On

;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;

max_execution_time = 30
max_input_time = 60
memory_limit = 128M

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On

;;;;;;;;;;;;;;;;;
; Data Handling ;
;;;;;;;;;;;;;;;;;

variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 8M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"

;;;;;;;;;;;;;;;;;;;;;;;;;
; Paths and Directories ;
;;;;;;;;;;;;;;;;;;;;;;;;;

doc_root =
user_dir =
extension_dir = "ext"
enable_dl = Off

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

file_uploads = On
upload_tmp_dir = "D:\xampp8_3_xxx\tmp"
upload_max_filesize = 2M
max_file_uploads = 20

;;;;;;;;;;;;;;;;;;
; Fopen wrappers ;
;;;;;;;;;;;;;;;;;;

allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60

;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;

extension=bz2
extension=curl
extension=fileinfo
extension=gettext
extension=mbstring
extension=exif      ; Must be after mbstring as it depends on it
extension=pdo_mysql
extension=pdo_sqlite
extension=sqlite3
extension=xsl
extension=zip

;;;;;;;;;;;;;;;;;;;
; Module Settings ;
;;;;;;;;;;;;;;;;;;;

[CLI Server]

cli_server.color = On

[Date]

[filter]

[iconv]

[imap]

[intl]

[sqlite3]

[Pcre]

[Pdo]

[Pdo_mysql]

pdo_mysql.default_socket=

[Phar]

[mail function]

SMTP = localhost
smtp_port = 25
mail.add_x_header = Off
mail.mixed_lf_and_crlf = Off

[ODBC]

odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1

[MySQLi]

mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =

[mysqlnd]

mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = On

[OCI8]

[PostgreSQL]

pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0

[bcmath]

bcmath.scale = 0

[browscap]

[Session]

session.save_handler = files
session.save_path="D:\xampp8_3_xxx\tmp"
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5

[Assertion]

zend.assertions = 1

[COM]

[mbstring]

[gd]

[exif]

[Tidy]

tidy.clean_output = Off

[soap]

soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5

[sysvshm]

[ldap]

ldap.max_links = -1

[dba]

[opcache]

[curl]

curl.cainfo="D:\xampp8_3_xxx\apache\bin\curl-ca-bundle.crt"

[openssl]

[ffi]

```
</details>

## [6] ※ browscap.ini 等（必要な場合）
必要に応じて、`D:\xampp8_2_12\php\extras\browscap.ini`を、`D:\xampp\php8_3_xxx\extras`フォルダにコピーするなどします。

この他にも、個別の環境で必要なファイルを php.ini に設定しているなどの場合は、
そのファイルを
`D:\xampp8_2_12\php`や`D:\xampp8_2_12\php\extras`フォルダなどから、
`D:\xampp\php8_3_xxx`や`D:\xampp\php8_3_xxx\extras`フォルダなどにコピーしておきます。

<details><summary>現在のツリー構造が見たい方はこちら</summary>

```
（現在のツリー構造）
D:
├─xampp
│  ├─php8_3_xxx------------------------[1]
│  │  │  php.ini-development-----------------------[5]
│  │  │  php.ini-----------------------------------[5]
│  │  └─extras
│  │        browscap.ini-------------------------------[6]
│  ├─apache
│  │  └─conf
│  │      └─extra
│  │            httpd-xampp8_2_12.conf-----[2]
│  │            httpd-xampp8_3_xxx.conf----[2]
│  ...
├─xampp8_2_12---------------------------------[3]
│  ├─php
│  │  │  php.ini-----------------------------------[5]
│  │  └─extras
│  │        browscap.ini-------------------------------[6]
│  ...
└─xampp8_3_xxx--------------------------------[3]
    ├─apache
    │  └─conf
    │      │  httpd.conf-------------------------[4]
    │      └─extra
    │             httpd-autoindex.conf------------[4]
    │             httpd-dav.conf------------------[4]
    │             httpd-manual.conf---------------[4]
    │             httpd-multilang-errordoc.conf---[4]
    │             httpd-ssl.conf------------------[4]
  ```

</details>

## [7] php8_3_xxx フォルダをコピー
(1) （**追記**）`D:\xampp8_3_xxx`フォルダには、元々「**php**」フォルダ（`D:\xampp8_2_12`フォルダ内の「**php**」フォルダと同じもの）があるはずなので、これを削除しておきます。

(2) 次に、`D:\xampp\php8_3_xxx`フォルダを、`D:\xampp8_3_xxx`フォルダにコピーし、「**php**」にリネームします。

<details><summary>現在のツリー構造が見たい方はこちら</summary>

```
（現在のツリー構造）
D:
├─xampp
│  ├─php8_3_xxx------------------------[1]---------------[7]
│  │  │  php.ini-development-----------------------[5]
│  │  │  php.ini-----------------------------------[5]
│  │  └─extras
│  │        browscap.ini-------------------------------[6]
│  ├─apache
│  │  └─conf
│  │      └─extra
│  │            httpd-xampp8_2_12.conf-----[2]
│  │            httpd-xampp8_3_xxx.conf----[2]
│  ...
├─xampp8_2_12---------------------------------[3]
│  ├─php
│  │  │  php.ini-----------------------------------[5]
│  │  └─extras
│  │        browscap.ini-------------------------------[6]
│  ...
└─xampp8_3_xxx--------------------------------[3]
    ├─apache
    │  └─conf
    │      │  httpd.conf-------------------------[4]
    │      └─extra
    │             httpd-autoindex.conf------------[4]
    │             httpd-dav.conf------------------[4]
    │             httpd-manual.conf---------------[4]
    │             httpd-multilang-errordoc.conf---[4]
    │             httpd-ssl.conf------------------[4]
    └─php-------------------------------------------------[7]
  ```

</details>

これで新しいバージョンの PHP 追加作業は終了です。
お疲れ様でした。

で...たぶん、これでちゃんとできてると思います........
XAMPP Control Panel で XAMPP を再起動すると、新しいバージョンの PHP が動くはずです。

PHP8_3_xxx のフォルダ（`D:\xampp\php8_3_xxx`と`D:\xampp8_3_xxx\php`）は、どちらか一つでいいのでは？
と思うこともありますが、面倒なので調べていません。

すべてを完全には確認していませんが、`phpinfo()`で新しいバージョン`8.3.xxx`が表示されたので、OKということにしています。もし何かあれば、教えてください。

:::note info
### 追記
`PHP8.3`で新しく導入された`mb_str_pad`関数が機能しました。

```PHP
echo mb_str_pad('あいう', 5, 'えお'); // あいうえお
```
:::



なお、私のところでは、MySQL, MariaDBともに使っていないので、使う場合は追加の設定が必要になると思います。（以前から使っている場合は、以前の`php.ini`の設定がそのまま使えるかもしれません。...たぶん...使えるんじゃないでしょうか？）


以上で終わりです。

:::note info
`D:\xampp\apach\logs\error.log`に、
> PHP Warning: PHP Startup: Unable to load dynamic library 'curl' ...

というエラーメッセージが書き込まれていることに気付いたので、それを修正する記事を追加しました。（↓下記）
:::


https://qiita.com/Qiibow/items/b2e9c9e83c62e51a5ac2