wyrihaximus/phpstan-react
PHPStan extension for ReactPHP projects that flags blocking PHP functions such as file_get_contents, fopen, and fclose, and points to async ReactPHP replacements from react/filesystem and react/socket. Install via Composer; rules auto-load with phpstan/extension-installer or include extension.neon.
Loop::… rather than injecting or storing LoopInterface, avoid Loop::get() indirection, and keep loop references out of domain models and promoted properties. This converts a code-review opinion into a CI gate, which is the decision a PM actually needs to fund (reviewer time vs. tooling time).sleep, usleep, time_nanosleep, file_get_contents, fopen, fread, fwrite, gethostbyname, mkdir, file_exists, is_dir, is_file, is_link, fclose) and names the ReactPHP replacement plus documentation link in each error message. For a product whose value proposition depends on responsiveness or concurrency, these are latent outages: one blocking file_get_contents in an event-loop handler stalls every in-flight request.react/async rules track which closures are wrapped in async and follow the call graph to catch indirect await reachability. This matters if the roadmap includes moving ReactPHP services toward fiber-style async; the tool surfaces the migration's sharp edges before runtime.parameters.wyrihaximus.reactphp.rules, so a PM can sequence adoption (blocking-call rules first, event-loop rules second, async rules third) and stage the engineering cost across sprints rather than in one large PR.Adopt when:
react/event-loop, react/socket, react/stream, react/filesystem, react/dns, react/promise-timer, react/async) and long-lived processes serve user-facing traffic.phpstan/extension-installer (or an explicit includes: entry) is in use, so marginal integration cost is one dependency plus one config line.Loop:: access, no injected loops) and you want that direction enforced automatically instead of by convention.async migration with guardrails before committing roadmap capacity to it.Look elsewhere when:
For executives, one paragraph. This is a free, MIT-licensed, dev-only quality gate for the part of our stack that handles many concurrent requests in a single long-running PHP process. It teaches our existing static analysis tool about ReactPHP so that blocking calls (sleep, file_get_contents, fopen and friends) and misplaced event-loop references fail the build instead of surfacing as production stalls. Cost is one dependency and one line of config, it never ships to production, and removing it is a one-commit reversal. It also gives us guardrails for the planned fiber/async work, so that migration is attempted with a safety net rather than blind.
For engineering leadership. Treat it as a review-automation investment, not a library adoption: it moves a recurring code-review conversation (use the async API, do not hold a loop reference, do not await outside an async closure) into PHPStan output with the suggested replacement and a documentation link attached to each violation. Rules are individually toggleable, so we can land blocking-call rules first and sequence the stricter event-loop rules behind team agreement, avoiding a single disruptive cleanup PR.
For engineering, the honest caveats to state up front. This is not a Laravel package; it applies only to our ReactPHP surfaces. It is a single-maintainer project with negligible download counts and no vendor support, so we should pin the version, expect to own any rule we need that upstream does not provide, and be prepared to fork. Coverage is limited to its documented function list: it will not detect blocking database or HTTP clients, so it complements rather than replaces load testing and performance budgets. Proposed pilot: enable on one ReactPHP service, run in non-blocking mode for two sprints to size the violation count, then promote to a CI gate and decide on the event-loop and async rule categories based on real findings.
How can I help you explore Laravel packages today?