PHP
1. What's in the catalogue
Four published lines — 8.2.33, 8.3.33, 8.4.24, 8.5.9 — pin with @8.2 … @8.5 (or the full version). As of catalogue 2026.35.22 (2026-08-25):
| Tool | Caps | Requires | Notes |
|---|---|---|---|
php | rw | — | the CLI; no composer tool in the catalogue — the composer provider brings composer into the environment build itself |
No declared-not-published PHP entries. No php-cs-fixer, no phpstan, no pest line in the catalogue either — see Tooling.
2. The five-minute version
kapsl php --version
PHP 8.5.9 (cli) (built: Aug 17 2026 13:28:18) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.5.9, Copyright (c), by Zend Technologies
with Zend OPcache v8.5.9, Copyright (c), by Zend Technologies
Run a script:
kapsl php app.php
The Composer-based form — composer install against your composer.json, into a scanned environment image, then the script:
kapsl -e @composer:composer.json php app.php
The composer provider is auto-detected by filename: in a directory with a composer.json, kapsl -e . php app.php picks it up. composer.lock is the companion file that makes the build reproducible.
3. The environment story: the vendor-directory redirect
Composer's install model is per-project by convention: composer install writes to ./vendor, autoloaded via __DIR__ . "/vendor/autoload.php" relative to the project root. But the environment build happens in an isolated build context, disconnected from the real working tree mounted at run time — a plain ./vendor from the build would not be where the run container's script looks.
So the provider redirects the install to a fixed, image-wide path: COMPOSER_VENDOR_DIR=/opt/composer/vendor. That mirrors gem's system gem directory and npm's NODE_PATH approach — the dependency set lives in the scanned image at a known absolute path, and the working tree stays clean. The practical consequence is one line in your bootstrap:
require '/opt/composer/vendor/autoload.php';
rather than the conventional __DIR__ . '/vendor/autoload.php'. The php-composer example (Monolog) does exactly this, and its README walks through the reasoning.
PECL extensions (native C) work too: composer install runs with g++/make apt-installed live against the composed PHP image, so ext-… packages that compile at install time succeed inside the environment build.
4. Tooling
No PHP linter or test runner is in the catalogue: no php-cs-fixer, no phpstan, no pest line. Until one publishes, linting is the IDE use case's territory, and test suites run through the environment itself — note the vendor path from the environment build: kapsl -e @composer:composer.json php /opt/composer/vendor/bin/pest — or through a project overlay that grants what the suite needs.
5. Project patterns
php-simple— the no-dependency shape:php app.phpunder kapsl, at the basic levels.php-composer— the full dependency story:composer installinto the environment, the/opt/composer/vendorredirect, and PECL/native-extension support.
6. Known limitations
- The fixed vendor path is a convention break. Your autoloader has to require
/opt/composer/vendor/autoload.php; the__DIR__-relative idiom PHP developers reach for by default will not find the dependency. One-line fix, but it shows up in every Composer project. - The catalogue side is thin. One tool, one provider, no linters — same honest state as Ruby. Projects that need
php-cs-fixertoday run it through a local[tools]mapping (see Tool mappings) or wait for a published line.