Computing: Website and Database Programming

Using multiple PHP versions on Apache for Windows.

One of the problems with PHP is that it is not backward compatible. Not only that functions included with the older version (for example, PHP 7) aren't anymore available with the newer version (for example PHP 8), but also, that code that worked well with the older version, doesn't work anymore with the newer one, because the syntax or the way a given feature used to work, have been changed. One of the problems, you may encounter when running a script, that you wrote for PHP 7, with PHP 8 is the error message Uncaught TypeError: Unsupported operand types. This happens, for example, if you try to add to variables, one of them containing an empty string, the other one an integer. With PHP 5, this wasn't a problem at all. With PHP 7, this produces a warning, but your script continues correctly. With PHP 8, the script aborts (in PHP 8, you have to set the variable to null instead of setting it to an empty string). It's obvious that it would be best practice to adapt your scripts or the newer version, when you migrate from the older one. But this could be really time-consuming, and in the case, where you use a PHP software package, that you got from some Internet site, it could be really heavy to make changes to code, that you haven't written yourself. In the case of a local website, used by yourself alone, running the PHP 7 software package with PHP 7 instead of PHP 8, would probably be the simplest way to do.

This presupposes, of course, that you have both PHP 7 and PHP 8 installed on your system. And the question is: How can we use both of them on our Apache webserver? I suppose (without being sure), that when running PHP scripts as CGI, it would be possible to use both versions of PHP "at the same time". On the other hand, if you run PHP as an Apache module, you can only use one PHP version at a time, i.e. you either start Apache with PHP 7, or with PHP 8. As you probably developed most of your scripts before PHP 8 was released, and if these scripts run with your actual PHP 8, they will run with PHP 7, too. So, you would normally run PHP 8, and switching to PHP 7, to run some "special" PHP 7 scripts, that do not run with PHP 8, and that you don't, for one reason or another, want to change for compatibility with PHP 8. That's what this tutorial is about. When writing it, I used Apache Lounge 2.4.57 with PHP 8.1.23 and PHP 7.4.33. The way to proceed should be the same for other versions.

My original system included Apache installed in C:\Programs\apache and PHP 8 installed in C:\Programs\php. I then downloaded PHP 7 and unpacked the download archive into the folder C:\Programs\php7, making the usual modifications to php.ini (that I copied from php.ini-development); cf. Web development environment setup on MS Windows: PHP.

I suppose that the most obvious way to proceed would be to install two separate Apache services, as explained in the article How to use multiple PHP versions with Apache on Windows on steemit.com. This consists in using a common httpd.conf, where the instructions to load the PHP 8 module are placed within a <ifdefine php8> ... </ifdefine> structure, and the the instructions to load the PHP 7 module are placed within a <ifdefine php7> ... </ifdefine> structure, and then installing the two Apache services (that you name, for example Apache_php8 and Apache_php7), using the options -n Apache_php8 -D php8 resp. -n Apache_php7 -D php7. Both Apaches should be listed in Apache Monitor, and you can choose to start either the one with PHP 8, or the one with PHP 7.

I chose a different way: using a single Apache service (in fact, letting my Apache service as it was installed), but two different httpd.conf. The first httpd.conf is my original configuration file (including the instructions to load the PHP 8 module), that I renamed to httpd_php8.conf. The second one is a copy of the original file, with the instructions to load PHP 7 replacing those to load PHP 8, and that I named httpd_php7.conf. I then wrote a batch file to control Apache, with the possibilities to stop the server, restart it (with the actual PHP version), start it with PHP 8, or start it with PHP 7.

Here the PHP specific instructions in my httpd_php8.conf:
    # PHP 8 support
    AddHandler application/x-httpd-php .php
    AddType application/x-httpd-php .php
    LoadModule php_module "C:/Programs/php/php8apache2_4.dll"
    PHPIniDir "C:/Programs/php/"

And the PHP specific instructions in my httpd_php7.conf:
    # PHP 7 support
    AddHandler application/x-httpd-php .php .php7
    AddType application/x-httpd-php .php .php7
    LoadModule php7_module "C:/Programs/php7/php7apache2_4.dll"
    PHPIniDir "C:/Programs/php7/"

Note the possibility to use the extension .php7 for scripts that require PHP 7 (because they are not PHP 8 compatible).

I placed the batch file in the directory C:\Programs and added this directory to the PATH environment variable. Thus, you can launch it directly in Command Prompt. Important: As the batch file starts a service, you'll have to choose to run Command Prompt as an administrator!

Here is the content of my apache.bat:
    @echo off
    c:
    cd \Programs\apache24
    if "%1"=="start" set _COMMAND=start
    if "%1"=="stop" set _COMMAND=stop
    if "%1"=="restart" set _COMMAND=restart
    if "%2"=="php7" set _PHP=7
    if "%2"=="php8" set _PHP=8
    if "%_COMMAND%"=="" goto NoCommand
    if "%_COMMAND%"=="start" goto Start
    if "%_COMMAND%"=="restart" goto Restart
    :Stop
    .\bin\httpd -k stop
    goto End
    :Restart
    .\bin\httpd -k restart
    goto End
    :Start
    if "%_PHP%"=="" goto NoPHP
    if "%_PHP%"=="7" set _CONF=httpd_php7.conf
    if "%_PHP%"=="8" set _CONF=httpd_php8.conf
    .\bin\httpd -k stop
    del .\conf\httpd.conf
    copy .\conf\%_CONF% .\conf\httpd.conf
    .\bin\httpd -k start
    goto End
    :NoCommand
    echo Missing or invalid command
    goto End
    :NoPHP
    echo Missing or invalid PHP version
    :End
    set _COMMAND=
    set _PHP=
    set _CONF=

The script requires at least one parameter: the command "stop", "restart", or "start"; in this latter case, a second parameter, "php8" or "php7" is required; any supplementary parameters specified are simply ignored. The command "stop" stops the Apache server, "restart" restarts it with the actual httpd.conf, i.e. with the actually used PHP version. When the command "start", together with the second parameter, that indicates the PHP version to be used, is specified, the script does the following: copy of either httpd_php8.conf, or httpd_php7.conf (depending on the second parameter) to httpd.conf (to avoid any problems, I httpd.conf is first deleted), then Apache is started, all the same way as it usually is (here again, to avoid any problem, Apache is first stopped).

Note: Apache searches for httpd.conf in the directory "conf" relative to its installation directory. That's why the current directory is set to C:\Programs\apache.

When I executed the script for the first time, Windows Defender Firewall issued a security alert (if you use a third party firewall, this may or may not be the case). The alert said that some features of Apache had been blocked and you must give Apache access to the (local) network. I suppose that this alert is due to the fact that the service is started by another program, resp. by a program located in a directory other than Program Files or Program Files (x86).

Security alert of Windows Defender Firewall, when trying to start the Apache service

The screenshot below shows the commands to start Apache first with PHP 8, then with PHP 7. The message "The Apache 2.4 service is not started" is misleading. It does not mean that Apache was not started, but it tells us that Apache was not running when the stop command was issued. To check if the correct PHP version has been loaded, you can have a look in the Apache error log, where a message concerning the configuration of PHP is always written to (even if there has been no error or warning).

Running a custom batch file to start Apache with either PHP 7, or PHP 8

Why I use this "unconventional way" to configure the usage of multiple PHP versions, you might ask. Probably because I wanted to have a single Apache service, because I wanted to keep my Apache service installed as it usually is, because I wanted to keep my original httpd.conf, because I didn't want to be bothered with ifdefine structures in httpd.conf and with the -D option in the Apache start command line... Anyway, the tutorial shows that there are always several ways to configure a given feature. And it also shows, that command line scripting is not only possible and useful on Linux, but also on Windows.


If you find this text helpful, please, support me and this website by signing my guestbook.