Set up a WordPress development environment using Homebrew on macOS

·

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:

wp-build.test 127.0.0.1
wp-src.test 127.0.0.1

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_SESION_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.

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.

In:

Tags:

One response to “Set up a WordPress development environment using Homebrew on macOS”

Leave a Reply

Your email address will not be published. Required fields are marked *