How to setup macOS Multi PHP Development Environment with MySQL and phpmyadmin

bambamboole
6 min readAug 20, 2017
Photo by Caspar Rubin on Unsplash

Disclaimer: This is my first medium post and I’m from germany so english is not my first language.

In my daily work I need a Setup with Apache and different PHP versions for different projects. I knew setups with cli commands for fast switching of apache php_module, but in my opinion this is a bit cumbersome.

After some research I came up with a solution which uses multiple php versions all running parallel in their own process.

In this tutorial we will setup a local PHP development with Apache, PHP 5.6, 7.0 and 7.1 as fpm processes, MySQL and phpmyadmin. We will configure Apache Auto Vhosts to recognize each folder in the ~/Sites directory a single Vhost. Additionally we use a custom DNS resolver and dnsmasq to redirect all DNS requests with the Top Level Domain .dev to the local Apache.

At the end of this tutorial you will be able to reach a sub folder from the ~/Sites directory in the browser by simply hitting http://{foldername}.dev to use it with PHP 5.6, http://{foldername}.dev:8070 to use it with PHP 7.0 and http://{foldername}.dev:8071 to use it with PHP 7.1

I assume that you have a clean macOS Sierra (I think it also works on other macOS versions) with working homebrew.

1. Prerequisites

First we have to disable the macOS built in Apache by using `launchctl`:

sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist

Next we need to add a few additional brew taps (third-party repositories).

brew tap homebrew/dupes
brew tap homebrew/versions
brew tap homebrew/php
brew tap homebrew/apache

2. Apache installation

Lets install apache by executing the following command:

brew install httpd24 --with-privileged-ports --with-http2 

the —-with-http2 option adds the http2 module to apache and the —-with-privileged-ports option lets apache uses the default ports 80 and 443 instead of 8080 and 8443 but requires root privileges fort startup. So we have to use sudo for adding apache to macOS startup as root.

sudo brew services start homebrew/apache/httpd24

3. PHP Installation

In the next step we install PHP 5.6 with some additional modules.

brew install php56 --with-fpm
brew install php56-mcrypt
brew install php56-opcache
brew install php56-apcu
brew install php56-xdebug
brew unlink php56

We need to unlink php56 that we can install additional versions. Lets install PHP 7.0.

brew install php70 --with-fpm
brew install php70-mcrypt
brew install php70-opcache
brew install php70-apcu
brew install php70-xdebug
brew unlink php70

Now we install PHP 7.1 :

brew install php71 --with-fpm
brew install php71-mcrypt
brew install php71-opcache
brew install php71-apcu
brew install php71-xdebug

We don’t need to unlink PHP 7.1 because we don’t install additional versions. As the result we use PHP 7.1 when we use php on the cli. You can verify this by calling the following command on the cli:

php --version

You will get a result similar to this one

PHP 7.1.6 (cli) (built: Jun 23 2017 08:42:14) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
with Xdebug v2.5.1, Copyright (c) 2002-2017, by Derick Rethans

When you need one of the other versions on the cli simple use brew unlink php71 and brew link php56 for example.

php-fpm listens by default on port 9000. But we want to run three parallel php processes so we need to edit the fpm listen directive in the fpm config.

nano /usr/local/etc/php/5.6/php-fpm.conf

Search for

listen = 127.0.0.1:9000

and change it to

listen = 127.0.0.1:9056

We will also change the default user from _www to our own user that we later don’t have permission issues while developing.

You can edit the php 7.0 fpm config with the following command

nano /usr/local/etc/php/7.0/php-fpm.d/www.conf

In this file we change the port from 9000 to 9070 to represent the 7.0 version. Don’t forget to change the user to you own user.

Just repeat that with the php 7.1 fpm config and use the port 9071 .

nano /usr/local/etc/php/7.1/php-fpm.d/www.conf

Now lets add all php processes to macOS startup with

brew services start php56
brew services start php70
brew services start php71

4. Apache configuration

Open Apaches httpd.conf with

nano /usr/local/etc/apache2/2.4/httpd.conf

and search for listen :80 and change it to listen 127.0.0.1:80 .

You also have to add the following listen directives which we will use for php 7.0 and 7.1

listen 127.0.0.1:8070
listen 127.0.0.1:8071

We have to add index.php to the DirectoryIndex that it looks like the following:

<IfModule dir_module>
DirectoryIndex index.php index.html
</IfModule>

We need this later that phpmyadmin works properly.

Next we need to uncomment (remove the # at the beginning of the line) a few lines in the httpd.conf . They are not each under the other, so maybe you have to search the lines:

LoadModule proxy_fcgi_module libexec/mod_proxy_fcgi.soLoadModule proxy_module libexec/mod_proxy.soLoadModule vhost_alias_module libexec/mod_vhost_alias.soLoadModule rewrite_module libexec/mod_rewrite.soInclude /usr/local/etc/apache2/2.4/extra/httpd-vhosts.conf

Next we have to add three vhosts. One for each php version. We configure the vhosts, that all folders in the directory ~/Sites/ are representing a single vhost. Apaches DocumentRoot will be in a folder called web in each vhost. Open Apaches httpd-vhosts.conf by calling:

nano /usr/local/etc/apache2/2.4/extra/httpd-vhosts.conf

You can delete every line in this file and add the following:

# Virtual Hosts
#
<Virtualhost *:80>
VirtualDocumentRoot "/Users/{username}/Sites/dev/%1/web"
ServerName vhosts.dev
ServerAlias *.dev
UseCanonicalName Off
LogFormat "%V %h %u %t \"%r\" %s %b" vcommon
CustomLog "/Users/{username}/Sites/dev/vhosts-access_log" common
ErrorLog "/Users/{username}/Sites/dev/vhosts-error_log"
<Proxy "fcgi://127.0.0.1:9056">
ProxySet timeout=3600
</Proxy>
<Directory "/Users/{username}/Sites/dev/*">
<FilesMatch "\.php$">
SetHandler proxy:fcgi://127.0.0.1:9056
</FilesMatch>
Options Indexes FollowSymlinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
</Virtualhost>
<Virtualhost *:8070>
VirtualDocumentRoot "/Users/{username}/Sites/dev/%1/web"
ServerName vhosts.dev
ServerAlias *.dev
UseCanonicalName Off
LogFormat "%V %h %u %t \"%r\" %s %b" vcommon
CustomLog "/Users/{username}/Sites/dev/vhosts-access_log" common
ErrorLog "/Users/{username}/Sites/dev/vhosts-error_log"
<Proxy "fcgi://127.0.0.1:9070">
ProxySet timeout=3600
</Proxy>
<Directory "/Users/{username}/Sites/dev/*">
<FilesMatch "\.php$">
SetHandler proxy:fcgi://127.0.0.1:9070
</FilesMatch>
Options Indexes FollowSymlinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
</Virtualhost>
<Virtualhost *:8071>
VirtualDocumentRoot "/Users/{username}/Sites/dev/%1/web"
ServerName vhosts.dev
ServerAlias *.dev
UseCanonicalName Off
LogFormat "%V %h %u %t \"%r\" %s %b" vcommon
CustomLog "/Users/{username}/Sites/dev/vhosts-access_log" common
ErrorLog "/Users/{username}/Sites/dev/vhosts-error_log"
<Proxy "fcgi://127.0.0.1:9071">
ProxySet timeout=3600
</Proxy>
<Directory "/Users/{username}/Sites/dev/*">
<FilesMatch "\.php$">
SetHandler proxy:fcgi://127.0.0.1:9071
</FilesMatch>
Options Indexes FollowSymlinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
</Virtualhost>

Pay attention that you replace all {username} with your own user name.

now create the used directories with

mkdir -p ~/Sites/dev

Now restart Apache by calling sudo apachectl restart .

5. dnsmasq installation and configuration

dnsmasq is a simple dns server which redirects .dev dns requests to Apache We can install dnsmasq with homebrew.

brew install dnsmasq

Edit the dnsmasq configuration by calling

nano /usr/local/etc/dnsmasq.conf

and add the following line to the top of the file:

address=/dev/127.0.0.1

add dnsmasq to macOS startup. We need to use sudo that it runs as root.

sudo brew services start dnsmasq

Next we add a custom dns resolver to macOS to use the dnsmasq nameserver we just configured. This can be done by simple create file with the name of the used Top Level Domain ( .dev ) without the dot with nameserver {ip.of.the.nameserver} as content. If the resolver directory doesn’t exist we have to create it with sudo mkdir -p /etc/resolver . Then create a file called dev with

sudo nano /etc/resolver/dev

and add the following content

nameserver 127.0.0.1

Now reboot macOS by typing sudo reboot in the cli.

To test the setup we create a project called test with just a phpinfo(); in the index.php .

mkdir -p ~/Sites/dev/test/web
echo "<?php phpinfo();" >> ~/Sites/dev/test/web/index.php

Now you can open http://test.dev to open the page with php 5.6.

When you open http://test.dev:8070 you will se the PHP info page wiht php 7.0 and by using the port 8071 you will see it with php 7.1 . Just awesome :-)

6. MySQL installation

We can install mysql with homebrew

brew install mysql

and add it to macOS startup with

brew services start mysql

Now lets configure mysql with the following interactive command:

mysql_secure_configuration

It’s up to you but you can use simple root password because in a later step you disallow remote login of root user.

7. phpmyadmin installation

Like MySQL we can install phpmyadmin with homebrew

brew install phpmyadmin

to say apache to recognize phpmyadmin we need to add the following to the end of /user/local/etc/apache2/2.4/httpd.conf .

Alias /phpmyadmin /usr/local/share/phpmyadmin
<Directory /usr/local/share/phpmyadmin/>
<FilesMatch "\.php$">
SetHandler proxy:fcgi://127.0.0.1:9056
</FilesMatch>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Allow from all
</IfModule>
</Directory>

Now restart apache with sudo apachectl restart and open http://localhost/phpmyadmin in your favorite browser and login with root and the password set while mysql configuration.

I hope you enjoyed the tutorial. If you have any additions or issues, please drop me a line.

--

--