I just bought an Intel NUC (Next Unit of Computing) mini-PC to serve as my secondary, Windows-powered development machine (the primary is an Apple Mac Mini). I decided it would be a fun* weekend project to implement an Apache-MySQL-PHP web server without using a pre-packaged server like XAMPP, WAMPServer etc. My goal was to have the same sites run under different versions of PHP by just visiting a different URL on my browser.
* for extremely geek values of "fun"
We'll need to do four steps. Set up the PHP versions we want to use, set up MySQL, set up Apache (and tell it how to run PHP), create as many virtual hosts per site as PHP versions we want to test with. It's not very hard to do, but it's not for Joe and Jane Average. A working understanding of system administration is prerequisite to carrying out the rest of the instructions. If the terms "command line", "configuration file", "system service" or "FastCGI" make you cringe or, worse, draws a blank stare please stop reading now and save your time and your sanity by downloading XAMPP. You're welcome.
Disclaimer: the following configuration is only meant to be used as a local development server. Furthermore, these instructions were tested on a fairly vanilla Windows 8.1 installation on a brand new Intel NUC. I am documenting them in a blog post because, well, I will forget how I did it in a couple of months. If it works for you too, cool bananas!
Pro tip: One great application for editing configuration files for PHP, MySQL and Apache with full syntax highlighting is Notepad++. It's free of charge too.
Setting up PHP
Download the latest PHP 5.3, 5.4 and 5.5 versions from http://windows.php.net/download/ Choose the Non Thread Safe releases.
Create a new empty folder C:\PHP
Extract each version of PHP in a directory under C:\PHP, i.e. C:\PHP\5.3 for the latest PHP 5.3 version, C:\PHP\5.4 for the latest PHP 5.4 version, C:\PHP\5.5 for the latest PHP 5.5 version.
Inside each PHP version's directory copy php.ini-development to php.ini and edit to match your preferences. There is one important change which is mandatory. Find the line
; extension_dir = "ext"
and change it to
extension_dir = "C:\PHP\5.3\ext"
remembering to use the correct path per version number. Otherwise PHP won't start.
Press WIN-BREAK on your keyboard. Click on Advanced System Settings. Click on the Environment Variables button. In the top section ("User variables for MyUserName") double-click on the Path variable and append:
;C:\PHP\5.4
to add PHP 5.4 to your Windows path.
Setting up MySQL
Download the installer from MySQL community edition and install it following the instructions. Remember to enable TCP/IP networking when asked.
Press WIN-BREAK on your keyboard. Click on Advanced System Settings. Click on the Environment Variables button. In the top section ("User variables for MyUserName") double-click on the Path variable and append:
;C:\Program Files\MySQL\MySQL Server 5.6\bin
to add MySQL command lin programmes to your Windows path.
Setting up Apache
Download from Apache Lounge. Make sure you are downloading the VC11 binares. Download both the Apache package and the respective modules package. You also need to install the Microsoft VC11 redistributable package if it's not already installed on your PC.
Extract the Apache ZIP package. Copy the Apache24 directory to C:\ so that you now have a directory C:\Apache24
Enable PHP
Extract the modules ZIP package. Go into the mod_fcgid-x.y.z (x, y and z are numbers) folder. Go into the mod_fcgid folder. Copy the file mod_fcgid.so into the C:\Apache24\modules folder.
Edit the file C:\Apache24\conf\httpd.conf and change the following lines, removing the # in front of them:
# LoadModule include_module modules/mod_include.so # LoadModule fcgid_module modules/mod_fcgid.so # LoadModule vhost_alias_module modules/mod_vhost_alias.so
Edit the file C:\Apache24\conf\extra\httpd-default.conf and add the following lines at the end:
FcgidInitialEnv PATH "c:/php/5.4.32;C:/WINDOWS/system32;C:/WINDOWS;C:/WINDOWS/System32/Wbem;" FcgidInitialEnv SystemRoot "C:/Windows" FcgidInitialEnv SystemDrive "C:" FcgidInitialEnv TEMP "C:/WINDOWS/Temp" FcgidInitialEnv TMP "C:/WINDOWS/Temp" FcgidInitialEnv windir "C:/WINDOWS" FcgidIOTimeout 64 FcgidConnectTimeout 16 FcgidMaxRequestsPerProcess 1000 FcgidMaxProcesses 50 FcgidMaxRequestLen 8131072 # Location of php.ini FcgidInitialEnv PHPRC "c:/php/5.4.32" FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 1000 <Files ~ "\.php$"> AddHandler fcgid-script .php FcgidWrapper "c:/php/5.4/php-cgi.exe" .php Options +ExecCGI order allow,deny allow from all deny from none </Files>
You may change c:/php/5.4 to c:/php/5.3 or c:/php/5.5 depending on the default version of PHP you want on your server.
Edit the fle C:\Apache24\conf\httpd.conf and change the line
# Include conf/extra/httpd-default.conf
to
Include conf/extra/httpd-default.conf
(just remove the leading hash sign)
Test PHP
Create a new file C:\Apache24\htdocs\phpinfo.php with the content
<?php <?php phpinfo(); ?>
Open a command prompt (WIN-R, type cmd and press Enter) then
C: cd C:\Apache24\Bin httpd.exe
On your browser visit http://localhost/phpinfo.php You should see the PHP information page. If not, review all the instructions above, you missed a step.
Back to the command prompt, press CTRL-C to stop Apache. Close this command prompt.
Install Apache as a system service
Press the Windows key, type cmd, right clck on Command Prompt and choose Run as Administrator. This opens an "elevated" command prompt. Type this:
C: cd C:\Apache24\Bin httpd.exe -k install
Bonus: autostart Apache Monitor on boot
Open one Windows Explorer window of the folder C:\Apache24\bin
Open a second Windows Explorer window of the folder C:\Users\YourUserName\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup where YourUserName is, obviously, your username on Windows.
Holding down the ALT key drag ApacheMonitor from the first window into the second.
This will auto-start the Apache Monitor tray icon on boot which monitors the status of the Apache server and lets you restart it easily.
The Virtual Hosts
Our goal is to have every site on our local server run under a different PHP version depending on the domain name we are using. The domain names we will be using are:
- local.web for PHP 5.4
- local53.web for PHP 5.3
- local55.web for PHP 5.5
You need to change your hosts file to have Windows map these fake domains to your local server. Add these lines to the hosts file:
127.0.0.1 local.web www.local.web 127.0.0.1 local53.web www.local53.web 127.0.0.1 local55.web www.local55.web
We will also be implementing dynamic virtual hosts. This means that when you have a directory C:\Apache24\htdocs\foobar you will be able to access this site both as http://local.web/foobar and http://foobar.local.web The latter is a better way to develop sites locally since most web scripts store image paths relative to the domain root. For this trick to work you'd need to add a few more lines to your hosts file:
127.0.0.1 foobar.local.web 127.0.0.1 foobar.local53.web 127.0.0.1 foobar.local55.web
Now the site in the directory C:\Apache24\htdocs\foobar will be accessible as http://foobar.local.web (PHP 5.4), http://foobar.local53.web (PHP 5.3) and http://foobar.local55.web (PHP 5.5). Cool! Let's make the changes in our server's configuration to make that happen.
Configure Apache for multiple PHP versions
Edit the C:\Apache24\conf\httpd.conf. Find the line
# Include conf/extra/httpd-vhosts.conf
and remove the leading hash sign so that it becomes
Include conf/extra/httpd-vhosts.conf
Now edit the C:\Apache24\conf\extra\httpd-vhosts.conf file and change its contents with:
# Default PHP virtual host (local.web) <VirtualHost *:80> ServerAdminThis email address is being protected from spambots. You need JavaScript enabled to view it. DocumentRoot "c:/Apache24/htdocs" ServerName www.local.web #ErrorLog "logs/dummy-host.example.com-error.log" #CustomLog "logs/dummy-host.example.com-access.log" common </VirtualHost> # Dynamic virtual hosts using vhost_alias, default PHP <VirtualHost *:80> ServerAlias *.local.web UseCanonicalName Off VirtualDocumentRoot "c:/Apache24/htdocs/%1" </VirtualHost> # PHP 5.5 virtual host (local55.web) <VirtualHost *:80> ServerAdminThis email address is being protected from spambots. You need JavaScript enabled to view it. DocumentRoot "c:/Apache24/htdocs" ServerName www.local55.web #ErrorLog "logs/dummy-host.example.com-error.log" #CustomLog "logs/dummy-host.example.com-access.log" common <Directory "c:/Apache24/htdocs"> <Files ~ "\.php$"> AddHandler fcgid-script .php FcgidWrapper "c:/php/5.5/php-cgi.exe" .php Options +ExecCGI order allow,deny allow from all deny from none </Files> </Directory> </VirtualHost> # Dynamic virtual hosts using vhost_alias, PHP 5.5 <VirtualHost *:80> ServerAlias *.local55.web UseCanonicalName Off VirtualDocumentRoot "c:/Apache24/htdocs/%1" <Directory "c:/Apache24/htdocs"> <Files ~ "\.php$"> AddHandler fcgid-script .php FcgidWrapper "c:/php/5.5/php-cgi.exe" .php Options +ExecCGI order allow,deny allow from all deny from none </Files> </Directory> </VirtualHost> # PHP 5.3 virtual host (local53.web) <VirtualHost *:80> ServerAdminThis email address is being protected from spambots. You need JavaScript enabled to view it. DocumentRoot "c:/Apache24/htdocs" ServerName www.local53.web #ErrorLog "logs/dummy-host.example.com-error.log" #CustomLog "logs/dummy-host.example.com-access.log" common <Directory "c:/Apache24/htdocs"> <Files ~ "\.php$"> AddHandler fcgid-script .php FcgidWrapper "c:/php/5.3/php-cgi.exe" .php Options +ExecCGI order allow,deny allow from all deny from none </Files> </Directory> </VirtualHost> # Dynamic virtual hosts using vhost_alias, PHP 5.3 <VirtualHost *:80> ServerAlias *.local53.web UseCanonicalName Off VirtualDocumentRoot "c:/Apache24/htdocs/%1" <Directory "c:/Apache24/htdocs"> <Files ~ "\.php$"> AddHandler fcgid-script .php FcgidWrapper "c:/php/5.3/php-cgi.exe" .php Options +ExecCGI order allow,deny allow from all deny from none </Files> </Directory> </VirtualHost>
Test the solution
We can now use three different domains to access the same content as different PHP versions. Let's try it:
- http://www.local.web/phpinfo.php reports PHP 5.4
- http://www.local53.web/phpinfo.php reports PHP 5.3
- http://www.local55.web/phpinfo.php reports PHP 5.5
All three URLs load the file C:\Apache24\htdocs\phpinfo.php.
An exercise to the reader
You could even possibly have different sites use different PHP versions without using a special URL, just by adding the relevant section to their .htaccess file. Can you see how to do it?
Hint: The <Directory> section in a virtual host configuration has the same effect as putting its contents inside a .htaccess file in that directory.
When I follow your steps my Apache Server throws an error after I configured the httpd-default.conf:
AH00526: Syntax error on line 86 of C:/Apache24/conf/extra/httpd-default.conf:
Invalid command 'FcgidInitialEnv', perhaps misspelled or defined by a module not included in the server configuration
By digging a bit in google I found out that the fcgi module isn't enabled so you forgot to put that line into your example:
LoadModule fcgid_module modules/mod_fcgid.so
After I integrated that line in my httpd.conf, Apache starts w/o errors.
Just one question, in httpd-default.conf you have set PHPRC as path to folder containing php.ini.
If I run PHP5 script, it loads php.ini from folder php56 (this one is in PHPRC). I understand that, but if I run PHP7 script, it loads php.ini from folder php71... How is that possible? I never put path to that folder.
Regarding the PHPRC, each version of PHP has its own block in your httpd-vhosts.conf file. Over there you set up the PHPRC per PHP version. Failing to do that, PHP will fall back to the PHPRC environment variable (see the PHP documentation) and if that also fails it will try using the same path as the PHP executable. I suppose what happens in your case is the latter.
Press the Windows Logo Key + R, type shell:startup, and then select OK. This opens the Startup folder.
Another cool trick to manage already installed startup items is to open Task Manager (you can use CTRL-ALT-DEL and pick it from the list), click on the Startup tab and enable / disable startup services as required. Very useful to get rid of all the gunk installed by various third parties, printer and media device drivers being the worst offenders.
extension=mysqli
extension=pdo_mysql
# Default PHP virtual host (local.web)
<VirtualHost *:80>
ServerAdmin webmaster@local.web
DocumentRoot "c:/Apache24/htdocs"
ServerName www.local.web
#ErrorLog "logs/dummy-host.example.com-error.log"
#CustomLog "logs/dummy-host.example.com-access.log" common
<!--</VirtualHost>
Allow from all"
Not working on apache 2.4
https://stackoverflow.com/questions/10925528/invalid-command-order-perhaps-misspelled-or-defined-by-a-module-not-included