Runtimes & frameworks
| Runtime | --runtime value |
|---|---|
| FrankenPHP worker mode | frankenphp |
| Laravel Octane | octane |
| RoadRunner | roadrunner |
| Swoole / OpenSwoole | swoole |
These are targets, not detections
Section titled “These are targets, not detections”Worker Safety does not detect which runtime your application uses. There is
no such check anywhere in the tool, and the report labels the list Analysis targets for that reason: it is the set of runtimes the scan reasons about,
chosen by you with --runtime (default: all four).
Nor is the absence of a runtime package in composer.json treated as evidence
that no persistent worker is involved. It is not reliable evidence: a runtime
can be installed outside Composer — FrankenPHP and RoadRunner are binaries — the
decision usually lives in deployment configuration the source tree never sees,
and a long-running queue worker holds process state across jobs without any of
these packages being present.
That last point is a reason not to trust the inference, not a claim of
support: queue workers are not an analysis target, --runtime has no value for
them, and no rule models a job lifecycle. The four runtimes in the table above
are the whole list.
The practical consequence is that nothing is hidden or downgraded because a runtime looks absent. That is deliberate: the most useful moment to run this tool is before the migration, when none of those packages are installed yet. Findings are conditional statements — what this code would do if it ran under a persistent worker — and reading them is still your job.
All four are analyzed by default. Selecting a subset narrows which rules run and
which runtimes each finding lists, and when exactly one runtime is selected the
console report adds that runtime’s specific caveat — for example, that Octane
resets container state between requests but never your own statics. Note that
octane.flush does not help there: it calls forgetInstance() on the
container bindings you list and never touches a static property, so a static
needs an explicit reset from a RequestReceived or RequestTerminated
listener.
Superglobals differ per runtime too. FrankenPHP worker mode resets $_GET,
$_POST, $_COOKIE, $_FILES, $_SERVER and $_REQUEST between requests and
documents $_ENV as the exception, which is why WS003 rates a $_ENV write
above a $_SERVER one.
Frameworks
Section titled “Frameworks”| Framework | Detection | Support |
|---|---|---|
| Laravel | laravel/framework, laravel/lumen-framework, illuminate/support |
Container-binding analysis (WS005, WS006), Laravel-aware event detection in WS009, framework-specific scan defaults. |
| Symfony | symfony/framework-bundle, symfony/symfony |
Scan defaults. The adapter is a ready extension point; v1 ships no Symfony-specific rules rather than guessing. |
| Plain PHP | fallback | All eight framework-independent rules. |
Detection is a read of composer.json and composer.lock. The framework itself
is never installed, loaded or booted, and Worker Safety does not depend on it.
A scoped() registration only silences WS005/WS006 when it uses the exact
same container key. Keys are plain array keys, so 'Shared' is not 'shared',
and aliases are deliberately not followed: forgetScopedInstances() unsets
$instances[$key] without resolving aliases, and bind() deletes the alias for
any key it re-registers — so alias(Ctx::class, 'a') plus scoped('a') leaves
the Ctx::class singleton alive. This key identity is separate from PHP
class-name identity, which stays case-insensitive when resolving a bound class
to its declaration.