env() outside config/", "don't use DB:: in controllers", "don't touch the legacy Billing namespace" is currently enforced by code review and memory. This package turns those decisions into CI failures — the decision becomes a build artifact rather than a wiki page.spaze/phpstan-disallowed-calls, or have an engineer write an in-house rule in a day or two. This evaluation is itself the product decision — pick deliberately, not by default.curl_* calls) is how a platform team makes "use the approved SDK" real without a policing process. Useful when you're consolidating after an acquisition or merging two codebases.eval, unserialize, md5/sha1 for credentials, shell_exec, and similar is a cheap control that maps to security review findings and audit questions. It converts a policy document into a pass/fail gate.Adopt when most of the following hold:
Look elsewhere — or don't adopt — when:
forbiddenFunctions-style configuration natively; you don't need a dependency for that.spaze/phpstan-disallowed-calls is the community default for this exact job, with a much larger user base. Choosing a 7-star, 0-dependent package over a widely adopted alternative needs a specific reason — better ergonomics, better Laravel fit, or an internal fork you intend to support.For executives: A very low-cost CI addition that converts our written engineering standards into automatic checks. The business value is not the tool — it's that architecture decisions stop being advisory. It gives us a number for migration and deprecation work ("412 remaining usages, down from 1,100") instead of a status color. Cost is negligible; the main risk is maintenance of a small open-source dependency, which we contain by pinning a version and keeping the configuration in our repo.
For engineering leadership: We already pay for PHPStan on every PR. This extends it so that "don't use X" is a build failure instead of a code review negotiation. It's the cheapest way to make ADRs enforceable and to get per-PR visibility into migration progress. The tradeoff is explicit: the package is small and lightly adopted, so we either (a) accept it as a thin, replaceable dependency, (b) use the more established spaze/phpstan-disallowed-calls instead, or (c) write the equivalent rule ourselves in a day or two. Recommendation is to decide that tradeoff intentionally and not let the tooling choice happen by accident.
The one-line version: It's a spell-checker for our architecture rules — cheap to try, trivial to remove, and it makes our standards actually true.
How can I help you explore Laravel packages today?