Multiple Projects, Multiple Versions of PHP: How to Easily Change PHP Version on a Mac

If you, like me, have updated to PHP 8 (see my recent blog on the topic) then you may be running into this problem. You stop working on your current project and you switch over to another one. You go to run a composer install (or some other command) and you realize… oh crap, this project is still running PHP 7.x. You immediately get an error like:

composer install
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Your lock file does not contain a compatible set of packages. Please run composer update.

  Problem 1
    - Root composer.json requires php ^7.3 but your php version (8.0.11) does not satisfy that requirement.

Much swearing ensues!

Thankfully, this is absolutely not a big deal and should take you all of about 10 seconds to resolve. Let me show you how!

Managing System Dependencies

If you’ve heard me talk about Devops, or you’ve followed along with my recommended host machine setup procedure, then you should have Homebrew on your machine. If you do, then this is literally two commands to resolve the problem (maybe three).

Part of the reason to use a dependency manager is exactly for circumstances like this. Changing around PHP versions in Mac OS is a pain in the butt (and I’ve done it in the past without Homebrew and 0/10 recommend).

To change PHP versions with Homebrew, here’s what you do:

brew unlink <current version of PHP>

brew link <desired version of PHP>

and that’s it.

So in my circumstances, I did this:

$ brew unlink php@8.0
Unlinking /usr/local/Cellar/php/8.0.11... 24 symlinks removed.

$ brew link php@7.4
Linking /usr/local/Cellar/php@7.4/7.4.24... 25 symlinks created.

You don’t have to restart your terminal, you don’t have to restart your webserver, it just works and it just works immediately. The one caveat you might run into is if you don’t have a particular version of PHP installed via Homebrew. In that case, you might need to also run a command like…

$ brew install php@7.4 

…and then you can run the brew link command.

When you’re done with the PHP 7.x project? Run the commands again in reverse to swap back to PHP 8.x (or whatever).

$ brew unlink php@7.4
Unlinking /usr/local/Cellar/php@7.4/7.4.24... 25 symlinks removed.
$ brew link php@8.0
Linking /usr/local/Cellar/php/8.0.11... 24 symlinks created.

Using Containers

There is another option to work around this, which I do sometimes take advantage of and that’s relying on the PHP version inside of my containers. For instance, I can be running PHP 8 on my host machine with a Lando container running PHP 7.4. If I run my composer command on the host machine, it will fail because of PHP 8. If I run it inside of the Lando container, it will be fine because of PHP 7.4. Those commands would be something like…

composer install

vs.

lando composer install

I will flag that this method doesn’t work well with Drupal VM because you cannot install Drupal VM via composer in the first place if your composer.json file requires a version of PHP that you don’t have on your host machine!

Defining Multiple PHP Versions

The final tip I’ll call out is that you can define multiple PHP versions in your composer.json. That looks something like:


"php": "^7.3 || ^8.0"


The advantage of this is that host machines like mine (running PHP 8) wouldn’t throw the same sort of errors. However, the you aren’t necessarily out of hot water here because a lot of php dependencies are locked into particular versions of PHP and just because your composer says “it’s ok to run PHP 8” doesn’t mean you can have dependencies for both… so you’ll essentially have to choose one version of PHP and you may still have problems.

the TLDR is that even doing the this trick, it’s best to pick a version of PHP and stick with it for that project.

In Conclusion

One of the biggest advantages of a containerized approach to local development is that you truly can change requirements between projects. But, obviously some of those requirement scan be problematic if they involve your host machine (and PHP always will). Hopefully Homebrew and some of the other methods in this article will help you next time you run into this!

Related Content