This is how long a request to /wp-admin
takes when served by Apache, PHP and MySQL running in a Docker container:
$ curl 'http://localhost:8888/wp-admin/' ... -s -o /dev/null -w "%{time_starttransfer}\n"
0.371047
This is how long a request to /wp-admin
takes when served by Apache, PHP and MySQL running natively on my computer:
$ curl 'http://wp-git-build.test/wp-admin/' ... -s -o /dev/null -w "%{time_starttransfer}\n"
0.060668
That’s a 310 ms difference! More than six times faster!
If you’re a WordPress contributor, you’re making thousands of these requests per day. You really owe it to yourself to take a bit of time and set up a fast development environment. You deserve it!
Here’s how to set up Apache, PHP, and MySQL for WordPress Core development using Homebrew and macOS.
0. Install Homebrew
Go and install Homebrew if you haven’t already. I’ll wait.
Throughout this tutorial, I’ll use paths that begin with /opt/homebrew
. This is where Homebrew will install files if you have a fancy new Apple Silicon Mac.
If you have an older Intel Mac, Homebrew will use /usr/local
, and you will need to replace /opt/homebrew
with /usr/local
wherever you see it.
You can check where Homebrew is installing files by running brew --prefix
.
1. Clone the wordpress-develop
repo
If you haven’t already, clone wordpress-develop
into wherever you keep your projects.
$ cd ~/projects
$ git clone git@github.com:WordPress/wordpress-develop.git
Then, build everything:
$ cd wordpress-develop
$ npm install
$ composer install
$ npx grunt build
2. Set up the web server
First, let’s install Apache, PHP, and MySQL:
$ brew install httpd php mysql
Now, open up the Apache config file in your favourite text editor. It’s located at either /opt/homebrew/etc/httpd/httpd.conf
or /usr/local/etc/httpd/httpd.conf
.
Now, change this line:
Listen 8080
To:
Listen 0.0.0.0:80
This makes Apache listen for all requests made to port 80.
Then, add this line underneath all of the lines beginning with LoadModule
:
LoadModule php_module /opt/homebrew/opt/php/lib/httpd/modules/libphp.so
This enables PHP on our Apache server.
Now, change this line:
DirectoryIndex index.html
To:
DirectoryIndex index.php index.html
This tells Apache to look for index.php
files when handling a request made to a directory.
Then, add this line underneath where you see </Files>
:
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
This tells Apache to handle any file ending with .php
as a PHP script.
Then, change this line:
#LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so
To:
LoadModule rewrite_module lib/httpd/modules/mod_rewrite.so
This enables rewrite rules in Apache, which WordPress uses to implement permalinks.
Now, change this line:
#Include /opt/homebrew/etc/httpd/extra/httpd-vhosts.conf
To:
Include /opt/homebrew/etc/httpd/extra/httpd-vhosts.conf
This tells Apache to load whatever configuration we put in httpd-vhosts.conf
.
Now, open /opt/homebrew/etc/httpd/extra/httpd-vhosts.conf
in your favourite text editor.
Delete the entire contents of this file and replace it with this line:
Include /opt/homebrew/etc/httpd/vhosts/*.conf
This tells Apache to log whatever configuration we put in the vhosts
folder. It’s a nice way of organising our configuration when Apache is set up to serve multiple websites.
Now, use your text editor to create a new file at /opt/homebrew/etc/httpd/vhosts/wp-build.test.conf
, and paste in this:
<Directory "/path/to/wordpress-develop/build">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<VirtualHost *:80>
ServerName wp-build.test
DocumentRoot "/path/to/wordpress-develop/build"
ErrorLog "/opt/homebrew/var/log/httpd/wp-build.test-error_log"
CustomLog "/opt/homebrew/var/log/httpd/wp-build.test-access_log" common
</VirtualHost>
This configures a new site called wp-build.test
, which serves the build
directory in wordpress-develop
. Be sure to replace /path/to/wordpress-develop
with the actual path to your wordpress-develop
folder.
Optionally, you can create another site called wp-src.test
for the src
directory in wordpress-develop
by creating an additional file at /opt/homebrew/etc/httpd/vhosts/wp-src.test.conf
:
<Directory "/path/to/wordpress-develop/src">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<VirtualHost *:80>
ServerName wp-src.test
DocumentRoot "/path/to/wordpress-develop/src"
ErrorLog "/opt/homebrew/var/log/httpd/wp-src.test-error_log"
CustomLog "/opt/homebrew/var/log/httpd/wp-src.test-access_log" common
</VirtualHost>
We’re nearly there. Edit /etc/hosts
and add these lines to the end of the file:
127.0.0.1 wp-build.test
127.0.0.1 wp-src.test
This configures the two .test
domains to resolve to your computer. You’ll need administrator privileges to edit this file. An easy way to gain that is to open your text editor using sudo
. For example, sudo code /etc/hosts
if you’re using Visual Studio Code.
Finally, we can start Apache and MySQL:
brew services start httpd
brew services start mysql
By using brew services
, Homebrew will automatically start Apache and MySQL when the computer turns on.
3. Install WordPress
We’re now ready to install WordPress.
First, let’s create a database:
$ mysql -u root -e "create database wp_build;"
Then, install WP-CLI.
$ brew install wp-cli
WP-CLI makes the next steps easier. It’s also a really handy tool to have for WordPress development.
Now, let’s create a wp-config.php
file using WP-CLI:
$ wp config create --path=build --dbname=wp_build --dbuser=root --dbpass=""
$ wp config set --path=build WP_DEBUG true --raw
$ wp config set --path=build SCRIPT_DEBUG true --raw
This create a new file in build/wp-config.php
.
Finally, we can run the WordPress installer:
$ wp core install --path=build --url=wp-build.test --title=wp-build --admin_user=admin --admin_password=password --admin_email=admin@example.com --skip-email
You should now be able to browse to http://wp-build.test/wp-admin and log in. The username is admin
and the password is password
.
Hooray!
Optionally, we can repeat all of the above for our site that is served out of src
, too:
$ mysql -u root -e "create database wp_src;"
$ wp config create --path=src --dbname=wp_src --dbuser=root --dbpass=""
$ wp config set --path=src WP_DEBUG true --raw
$ wp config set --path=src SCRIPT_DEBUG true --raw
$ wp core install --path=src --url=wp-src.test --title=wp-src --admin_user=admin --admin_password=password --admin_email=admin@example.com --skip-email
Bonus: Set up ImageMagick
If ImageMagick is installed then WordPress is able to do some neat image manipulation. Here’s how to configure it:
$ brew install imagemagick pkg-config
$ pecl install imagick
$ brew services restart httpd
If you get a “missing pcre2.h” error while running pecl install imagick
, try running ln -s /opt/homebrew/include/pcre2.h /opt/homebrew/Cellar/php/8.0.12/include/php/ext/pcre/pcre2.h
.
Bonus: Set up Xdebug
While we’re investing in our developer productivity, it’s definitely worth setting up Xdebug. First, install Xdebug:
$ pecl install xdebug
Now, open /opt/homebrew/etc/php/8.0/php.ini
in your favourite text editor and add this line to the top of the file:
xdebug.mode="debug"
You’ll then need to configure your IDE and use XDEBUG_SESSION_START
or a browser plugin to initiate debugging sessions.
Check out the Xdebug website for instructions. It’s not as hard as it sounds!
Bonus: Set up phpmyadmin
Hey, why not? Let’s install phpMyAdmin:
$ brew install phpmyadmin
Now, create a new file at /opt/homebrew/etc/httpd/vhosts/phpmyadmin.test.conf
:
<Directory "/opt/homebrew/share/phpmyadmin">
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>
<VirtualHost *:80>
ServerName phpmyadmin.test
DocumentRoot "/opt/homebrew/share/phpmyadmin"
ErrorLog "/opt/homebrew/var/log/httpd/phpmyadmin.test-error_log"
CustomLog "/opt/homebrew/var/log/httpd/phpmyadmin.test-access_log" common
</VirtualHost>
This creates a new website called phpmyadmin.test
.
Now, open /opt/homebrew/etc/phpmyadmin.config.inc.php
in a text editor and change this line:
$cfg['Servers'][$i]['AllowNoPassword'] = false;
To:
$cfg['Servers'][$i]['AllowNoPassword'] = true;
This lets you log into phpMyAdmin using the root user with an empty password field.
Then, add phpmyadmin.test
to your /etc/hosts
file, as before:
127.0.0.1 phpmyadmin.test
Finally, restart Apache:
$ brew services restart httpd
You should now be able to browse to http://phpmyadmin.test and hack away!
Bonus: Set up phpunit
It’s a lot faster to run the WordPress unit tests locally than it is in Docker. Here’s how to set it up.
First, create an empty database for the tests to use:
$ mysql -u root -e "create database wp_tests;"
Then, copy the wp-tests-config-sample.php
file to wp-tests-config.php
:
$ cp wp-tests-config-sample.php wp-tests-config.php
Now, edit wp-tests-config.php
. Set DB_NAME
to 'wp_tests'
. Set DB_PASSWORD
to ''
. Finally, replace all of the salt constants with the output you get from browsing to https://api.wordpress.org/secret-key/1.1/salt/.
Bonus: Set up Gutenberg
This all works really well for Gutenberg development, too! Just clone the Gutenberg repo somewhere and then link to it from the plugins
directory.
$ git clone git@github.com:WordPress/gutenberg.git
$ cd gutenberg
$ npm install
$ npm run build
$ ln -s "$PWD" /path/to/wordpress-develop/build/wp-content/plugins/gutenberg
You’ll then see the Gutenberg plugin appear in the Plugins screen.
Leave a Reply