How to setup macOS Multi PHP Development Environment with MySQL and phpmyadmin
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.