Run several PHP versions side by side
On this page
Short Leash installs PHP 8.0 to 8.5, and PHP 8.6 as a preview, from static-php-cli builds, which include the extensions most frameworks need. New installs use PHP 8.5 by default, and Short Leash installs the default version when it starts, so the first site doesn't wait for a download. Install other versions on the Runtimes screen.
PHP 8.6 preview
Short Leash installs PHP 8.0 to 8.5, and PHP 8.6 as a preview: the newest release candidate, for trying your app before 8.6 is released. A preview is never the default and is never picked from composer.json while a released version fits; pin it to a site to use it. Xdebug isn't available for previews yet, and some extensions may be missing until 8.6 is released (leash php -m lists them). On Windows the preview comes from windows.php.net's test builds, checked against the SHA-256 they list. They need Microsoft's Visual C++ Redistributable 14.51 or later; on an older one, installing the preview says so, and so does a site that uses it, until you install the latest from Microsoft (Windows).
The Runtimes screen marks the row Preview, and a site's PHP version picker lists it as 8.6 (preview). On a Mac, Short Leash's preview build doesn't have these extensions yet, because they don't build against PHP 8.6: apcu, ev, event, excimer, grpc, igbinary, imagick, memcached, msgpack, pcov, pdo_sqlsrv, redis, sqlsrv and swoole. A site whose composer.json needs one of them gets a released version suggested under Needs a look. When PHP 8.6 is released, Short Leash offers it like any other version, and an installed preview updates to the release. Why it works this way: ADR 0083.
Default and per-site versions
The default version serves every PHP site that doesn't ask for another. Change it on the Runtimes screen or with:
leash use 8.5
A default you chose before stays as it is. When it's older than the newest version Short Leash supports, the Runtimes screen says so and offers Make 8.5 the default.
Pin a site to another version on its Site settings, or:
leash isolate 8.2 --site legacy
A site that isn't pinned follows its composer.json. Short Leash picks its version in this order:
- The version picked for the site.
- Otherwise the default, when
require.phpincomposer.jsonallows it, or the project has nocomposer.jsonorrequire.phpShort Leash can read. - Otherwise the newest installed version that
require.phpallows. - Otherwise the default.
So composer.json moves a site off the default only when the default doesn't fit it. Short Leash never installs a version because composer.json asks for one. The site's Overview says where its version comes from: picked for this site, from composer.json, or Short Leash's default. When no installed version fits, Needs a look says which one to install, and for a pinned site, which one to pick. A change applies on the next request; the site's background processes pick it up when they restart.
Each version runs its own PHP-FPM pool, started on the first request.
Settings
Runtimes › PHP settings sets these for every version:
| Setting | Default |
|---|---|
memory_limit |
512M |
upload_max_filesize and post_max_size |
100M |
max_execution_time |
120 seconds |
For anything else, add .ini files to php/conf.d in Short Leash's folder (~/Library/Application Support/Short Leash on a Mac) for every version, or to php/8.4/conf.d for PHP 8.4 only. Short Leash's settings load first, then the shared folder, then the version's, so the version's own files win. php.ini for 8.4 on a PHP row opens that version's folder, and Edit your php.ini files on the PHP heading opens the shared one, both in your editor. Saving the PHP settings restarts PHP, which also picks up changed files.
Laravel Octane
A Laravel site that requires laravel/octane can run on Octane instead of PHP-FPM. Pick Octane with Swoole or Octane with FrankenPHP under Served by on the site's Site settings, or:
leash octane frankenphp
leash octane off
Short Leash runs php artisan octane:start on a port it picks and serves https://<name>.test from it. The site keeps its PHP version and Short Leash's PHP settings.
- Swoole is built into Short Leash's PHP on macOS. Its short names, the global
go()andchan, are off (swoole.use_shortname = Off), so an app that declares its owngo(), like Kirby, still loads;Swoole\Coroutine\runand the rest of Swoole's classes and functions work as usual. - FrankenPHP is downloaded from its GitHub releases the first time you pick it, checked against the SHA-256 GitHub publishes. It runs the PHP it was built with. On Windows it's the only choice.
Octane keeps your app in memory, so code changes need a reload. Short Leash passes --watch when the project has chokidar (npm install --save-dev chokidar); otherwise, stop and start the site after a change.
Extensions
Short Leash's PHP builds include the extensions most apps need, such as intl, gd, imagick, redis, pdo_pgsql, swoole and sodium. Run leash php -m to see them all. Once Short Leash's own builds are published for a version, Short Leash installs those instead, and keeps using them; each new PHP patch release is built within a day. They add igbinary, msgpack, mongodb, ldap, gettext, excimer, grpc, ev, sqlsrv, pdo_sqlsrv and memcached, and gd reads and writes AVIF. mbstring includes its regular expression functions (mb_split, mb_ereg), which Laravel uses. For code coverage, the CLI loads pcov, so php artisan test --coverage works without Xdebug; sites served by php-fpm never load it. When Short Leash rebuilds a release it has already installed, for example to add an extension, it replaces the installed copy within a day and restarts that version's PHP. imap is in the PHP 8.2 and 8.3 builds only, because PHP 8.4 moved it out of PHP. There's no protobuf extension, because it can't be built alongside grpc; the google/protobuf Composer package works without it. Short Leash downloads them from its own server and checks them against a signed list of SHA-256 sums.
A site's Overview lists, under Needs a look, the extensions its composer.json and composer.lock need that the site's PHP version doesn't have, with what to do about each: pick a PHP version that has it, turn Xdebug on for that version, update a version installed before Short Leash built its own (Short Leash's current build has the extension), or nothing, because the extension doesn't exist for PHP on this system. On Windows, when PHP didn't load an extension the official build ships, the check says to run php -m in the site's folder, which prints why (usually a DLL the extension needs is missing). When no PHP version in Short Leash has the extension yet, the check says so ("No PHP version in Short Leash has oci8 yet."): Short Leash can't install it for you, so load it yourself with an extension= line in an .ini file in your conf.d folder, or run the app in a container with the extension and point the site at it with Port. The check skips Octane sites on FrankenPHP, because FrankenPHP runs the PHP it was built with. Short Leash asks the installed PHP what it loads (php -m with Short Leash's settings and your .ini files), so an extension you load from your own conf.d counts. A package that provides an extension, such as symfony/polyfill-mbstring, counts as having it, and so does an extension config.platform in composer.json names. Coding assistants get the same list from the check_extensions MCP tool.
On Windows
PHP on Windows comes from windows.php.net's official builds. Short Leash loads their common extensions plus gettext, ldap, ffi, dba, odbc, pdo_odbc, tidy, enchant, shmop and sysvshm, and imap on PHP 8.3 and older.
Short Leash adds redis, apcu, igbinary, msgpack, mongodb, opentelemetry, grpc, sqlsrv and pdo_sqlsrv for every version from PHP 8.0 to 8.5, except igbinary on PHP 8.5 (its current release doesn't build there yet) and opentelemetry on PHP 8.0 (it needs 8.1). The PHP 8.6 preview has the official build's extensions only. Each is built for its PHP version, or for mongodb, sqlsrv and pdo_sqlsrv taken unchanged from the extension's own project, then downloaded from Short Leash's server and checked against the signed list of SHA-256 sums. pcov loads for the CLI only, so php artisan test --coverage works and sites never load it. Installed versions pick up new extensions within a day: Short Leash replaces the version and restarts its PHP. If Short Leash can't reach its server while it installs a PHP update, that version runs with the official build's extensions until Short Leash adds its own, within a day.
Connecting to SQL Server with sqlsrv or pdo_sqlsrv also needs Microsoft's ODBC Driver for SQL Server. Installing it needs administrator rights, so Short Leash doesn't install it: get it from Microsoft's download page for the ODBC Driver for SQL Server.
Not on Windows: pcntl, posix, sysvmsg, sysvsem, swoole, excimer, memcached, event, ev and imagick. Each needs something Windows doesn't have or has no Windows build Short Leash can use; imagick's ImageMagick can't find its image readers when it's loaded from PHP's folder. Octane on Windows uses FrankenPHP.
Composer
Short Leash downloads Composer and checks it against the SHA-256 getcomposer.org publishes. leash composer …, or composer once Short Leash is on your PATH, runs it with the folder's PHP.