PHP versions
Butler can run several PHP versions side by side. You set one as the global default and override it per project whenever you need to.
Set the global default
Section titled “Set the global default”butler use 8.3Every site that hasn’t pinned its own version uses this one. You can also set the global version from the PHP section of the menu bar app.
Install another version
Section titled “Install another version”If a version isn’t installed yet, add it:
butler install php@8.4Installed versions appear in the app’s PHP section, where you can switch the default or install more with a click.
Pin a version to one site
Section titled “Pin a version to one site”To run a single project on a different PHP version without changing your global
default, run butler isolate from the project directory:
cd ~/Sites/my-appbutler isolate 8.2Or target a site by name with --site from anywhere:
butler isolate 8.2 --site my-appNow my-app.test uses PHP 8.2 while everything else stays on the default. Undo it
with butler unisolate (also auto-detects from the current directory, or takes a
site name):
butler unisolate my-appYou can also pin the version in the project’s
butler.yml, which is handy because it travels
with the repo:
php: "8.2"A Valet-style .valetphprc (a file containing just 8.2) works too, so a
project moved over from Valet keeps its pinned version without changing
anything. butler.yml wins if a project has both.
Run PHP and Composer
Section titled “Run PHP and Composer”butler php runs the active PHP for the current directory — the isolated
version if the folder is a site with one pinned, otherwise your global default:
butler php -vbutler php artisan migratebutler composer runs Composer through that same PHP, so your dependencies are
resolved against the version the site actually uses:
butler composer installbutler composer require laravel/pint --devThis matters more than it looks: Composer resolves platform requirements against
the PHP it runs on, so resolving a site pinned to 8.1 with a global 8.4 writes a
composer.lock the site can’t satisfy — usually noticed only when someone
reaches for --ignore-platform-reqs.
Override it for one call with --php <ver>, or target another site from
anywhere with --site <name>:
butler composer --php 8.4 require laravel/frameworkbutler composer --site my-app installGlobal Composer tools (laravel, pint, pest) are the exception — they
aren’t operating on the project you happen to be standing in, so they keep a
predictable version: whatever butler composer-tools set <tool> <ver> pins,
else the global default. Composer itself can’t be pinned that way, and
butler composer-tools shows it as follows the site: a global pin would
resolve every project’s dependencies against the wrong PHP, which is the
problem per-site resolution exists to avoid.
This means you don’t have to juggle a system PHP or remember which version is on
your PATH — Butler always uses the right one for where you are.
Bundled extensions
Section titled “Bundled extensions”Every PHP version ships as a single static binary with a broad set of extensions
compiled in — no pecl install, nothing to enable. This includes the ones a
Laravel or general PHP app expects: pdo_mysql/pdo_pgsql/pdo_sqlite,
mbstring (with mbregex), intl, gd and imagick, redis, mongodb,
bcmath, gmp, sodium, openssl, curl, zip, readline (so php -a
works), ffi, ldap, msgpack/igbinary, password-argon2 (Argon2id
hashing), and more. Xdebug ships alongside as a load-on-demand extension —
off by default, enabled per-invocation with XDEBUG_MODE (e.g.
XDEBUG_MODE=debug butler php ...).
Image formats
Section titled “Image formats”Both image extensions are built in — imagick links ImageMagick’s library
statically into the PHP binary, so there’s no magick/convert CLI to install.
Format support:
| Format | Imagick | GD |
|---|---|---|
| JPEG / PNG / GIF | ✅ | ✅ |
| WebP | ✅ | ✅ |
| AVIF | ✅ read + write | ✅ read + write |
| HEIC / HEIF | ✅ read only | — |
| JPEG XL, TIFF | ✅ | — |
HEIC (iPhone photos) can be decoded — so converting a .heic upload to WebP
or JPEG works — but not written back out as HEIC. Everything else, including
modern AVIF, is read/write on both extensions.
Tuning php.ini
Section titled “Tuning php.ini”Butler ships each PHP version with an ini tuned for real frameworks (sensible
memory limits, OPcache settings and so on). If you’ve edited a version’s php.ini
and want to get back to Butler’s defaults, reset it from the PHP section of
the app. Per-site PHP settings can also be set in
butler.yml:
server: phpSettings: memory_limit: "1G"