Develop and run PHP applications like WordPress and Laravel on your Mac

Paper figure in front of a board of PHP code.
Be like a proton. Always positive.

I've determined that this stack is my preferred environment to develop and run PHP applications, like WordPress and Laravel, on my MacBook. It's less ambiguous than tools that do everything for me, so I have a bit more control and flexibility, and I'm able to run 99% of my projects.

Whenever I work on a project that doesn't fit this stack, I spin up a virtual machine using one of my Docker templates. That way, I'm not constantly reconfiguring my environment and breaking things in the process– we've all been there.

If you have a Mac and are getting into PHP development, or if you're looking for a different way to manage your projects, this article is for you.

Install Oh My Zsh

Oh My Zsh is a framework that enhances your Terminal. Aside from cleaning up your Terminal's prompt and being Git-friendly, it also adds a number of Git shortcuts. Once you learn them, you'll be incredibly efficient.

To install Oh My Zsh, run this:

sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

Once complete, restart Terminal for the changes to take effect.

I keep a list of my most-used Git shortcuts, but feel free to peruse the full list of Git shortcuts to get an idea of what's available.

Install Homebrew

Homebrew is a package manager for Mac and Linux like NPM is for Node. We're going to use Homebrew to install PHP and MySQL, which are the bread and butter of PHP applications like WordPress and Laravel (although you could use a different database system if you wanted).

Let's install Homebrew:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Confirm Homebrew successfully installed by running:

brew --version

And you should see Homebrew's version:

Homebrew 3.6.4
Homebrew/homebrew-core (git revision f6b02a8ba16; last commit 2022-10-03)

If you get an error that the command could not be found:

zsh: command not found: brew

You'll have to include Homebrew's bin directory in your path, which essentially tells Terminal to look for executable files in that directory.

Edit a file called .zprofile in your home directory:

vi ~/.zprofile

And ensure /opt/homebrew/bin is in your path, for example:

export PATH="/opt/homebrew/bin:$PATH"

If you already have something in there, simply append it with another colon:

export PATH="/another/path:/opt/homebrew/bin:$PATH"

Install PHP

Let's install the latest version of PHP. You could install any version of PHP by adding the version to the end like so: [email protected]. You can even install multiple versions of PHP if different projects have different requirements.

To install PHP, run this:

brew install php

Confirm PHP successfully installed by running:

php --version

And you should see PHP's version:

PHP 8.1.11 (cli) (built: Sep 29 2022 19:44:28) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.11, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.11, Copyright (c), by Zend Technologies

Install and configure MySQL

Let's install the latest version of MySQL.

brew install mysql

Next we have to start the MySQL service:

brew services start mysql

After which we can finish the MySQL installation:

mysql_secure_installation

Set up validate password component? (No)

When you're prompted to set up the validate password component, press ENTER to skip it. On a production server, it would be highly recommended to set up, but since we're only using MySQL locally, we're going to keep things simple.

Securing the MySQL server deployment.

Connecting to MySQL using a blank password.

VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?

Press y|Y for Yes, any other key for No:

Enter root password

This will become the master password for MySQL:

Please set the password for root here.

New password: 

Re-enter new password: 

Remove anonymous users? (Yes)

You'll be asked if you want to remove anonymous users. Press y and ENTER to remove the users; there's no reason to keep them around.

By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No):

Disallow root login remotely? (Yes)

You'll be asked if you want to prevent remotely logging in to MySQL. Press y and ENTER to prevent it. There's no need because we're connecting to MySQL locally.

Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No):

Remove test database and access? (Yes)

You'll be asked whether you want to remove the test database. Press y and  ENTER, because we won't need it.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No):

Reload privilege tables now? (Yes)

You'll be asked if you want to reload privileges. Press y and ENTER so that our changes take effect.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No):

Test MySQL connection

You can test that everything was set up correctly by connecting to MySQL. When prompted, enter the password you chose earlier.

mysql -u root -p

If you see the MySQL prompt, you're all set:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.0.30 Homebrew

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

Type exit and press ENTER to log out.

If you have a MySQL client, you can also connect with the following:

  • Host: 127.0.0.1
  • User: root
  • Password:

Install Composer

Let's install Composer, which is a dependency manager for PHP. Go to Composer's official download page and copy the snippet at the top that looks like this:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

The install script, specifically the checksum, changes with each release, so you'll want to get the latest copy.

Once that is done, there will be a new file in your directory called composer.phar. We're going to move it into our local bin directory so we can run Composer from anywhere on our computer:

sudo mv composer.phar /usr/local/bin/composer

Confirm Composer installed successfully by running:

composer --version

And you should see Composer's version:

Composer version 2.4.2 2022-09-14 16:11:15

Install Valet

We're going to need a web server to serve our websites. On top of that, it would be nice if we could map local domains to our application so we don't have to start and stop each application because they're running on the same port, or keep a spreadsheet of which application runs on which port.

Laravel's Valet installs and configures two things (Nginx and Dnsmasq) we need, and you can use it for any PHP application, not just Laravel.

Let's install the Valet package globally using Composer:

composer global require laravel/valet

Just like with Homebrew, we'll have to add Composer's bin directory to our path so we can execute the applications we installed with it.

Move into your home directory and enter pwd (presently working directory) to get your home directory's path:

cd ~ && pwd

Note your username (/Users/<username>), edit your .zprofile again with vi ~/.zprofile, and add Composer to the path:

export PATH="/opt/homebrew/bin:/Users/<username>/.composer/vendor/bin:$PATH"

Close Terminal, reopen it, and check if the Valet package was successfully installed by running:

valet --version

Now that we have the Valet package, let's actually install Valet, which installs Nginx and Dnsmasq behind the scenes using Homebrew:

valet install

Serve a project

Find a place on your Mac to put a test file. I keep all of my projects in a Projects directory. If you want to follow this model, let's create a demo directory there:

mkdir -p ~/Projects/demo

And then move into it:

cd ~/Projects/demo

Let's create a simple PHP file to print "Hello World":

echo "<?php \$project = 'Hello World'; echo \$project;" > index.php

Then set up a .test domain of your choice to access the site (this will map demo.test to your project):

valet link demo

If you want to use SSL via a self-signed certificate, you can run:

valet secure

And last, open the project in a browser:

valet open

Useful Valet commands

  • Don't want to be prompted for a password in Valet? valet trust
  • Want to see all sites configured with Valet? valet links
  • Issues with Valet? valet restart

Additional troubleshooting

There will likely come a time when something isn't working quite right. For instance, I recently had an issue with projects not loading. To help troubleshoot problems with Valet, PHP, Nginx, or Dnsmasq, there is a tool called PHP Monitor.

You can install it with Homebrew:

brew install --cask nicoverbruggen/homebrew-cask/phpmon

You'll now have PHP Monitor in your list of applications on the Mac.

After you launch it, click the toolbar icon (displaying your PHP version) to the left of your system clock up top.

See if you have checkmarks for: PHP, Nginx, and Dnsmasq.

If not, explore the First Aid & Services option, specifically, Fix My Valet and Restore Homebrew Permissions. Also try to restart your Valet and Mac.

Note that you don't necessarily need PHP Monitor. You can do everything via the command-line as well, but it's a nice GUI to get an overview.

Now that you have the basics, take a look at how to set up Xdebug to debug your PHP applications and an autocomplete bash function (that works with Zsh) to quickly navigate in and out of your code projects.

If you have any questions or get stuck along the way, I'd love to hear from you in the comments below.

Featured image by KOBU Agency.