phpstan-strict-rules makes PHPStan reject the loose parts of PHP
Extra strict and opinionated rules for PHPStan
At a glance
- What is it?
- phpstan-strict-rules is a PHPStan extension that adds opinionated checks against loose comparisons, implicit casts and untyped conditions for teams writing defensive PHP. It is a large, deliberate jump in strictness rather than a drop-in extra.
- Who is it for?
- Adopt phpstan-strict-rules when the team wants PHPStan to enforce one strict dialect across a codebase, and expect to spend the first week turning rules off where the project has to live with legacy code. Do not add it to a project that only needs a higher analysis level, because the package also changes default values of PHPStan's own parameters.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
PHPStan finds bugs, this package decides which PHP idioms count as bugs
The premise of phpstan-strict-rules is stated in the first line of the project description: PHPStan focuses on finding bugs in your code, but in PHP there is a lot of leeway in how stuff can be written. The extension exists for developers who want additional safety in extremely defensive programming. That framing matters, because the rules are not about finding crashes. They are about removing constructs that behave predictably but weakly, and about forcing types to be explicit where the language would happily infer something. The package is a set of roughly two dozen configurable rules, each with a name, a description and its own on or off switch. Nothing here is exotic: the checks concern booleans, casts, comparisons, function arguments, array access and inheritance contracts. The value of collecting them is that a team can adopt a house style of strictness once, in configuration, rather than repeating the same arguments in every pull request.
Rules are wired in through rules.neon, and phpstan/extension-installer does the work
Mechanically, the extension is a normal Composer package that ships a neon configuration file. Installing phpstan/extension-installer is enough to have the rules registered, and if you would rather not add that package, the project's own configuration can include the shipped file directly. The repository layout shows how little there is to maintain: a rules.neon file at the top level, a phpstan.neon for the package's own analysis, a src directory holding the rule implementations, tests, and a collision-detector.json. That last file, together with a name-collision target in the Makefile, suggests the project checks that its rule identifiers do not clash with other extensions. Rules are addressed by a parameters block named strictRules, where each key matches a rule name from the table, and a separate allRules switch exists to turn the entire set off at once. That structure is what makes a gradual adoption possible.
Adding the extension takes one Composer command
Installation is a development dependency, since the rules only matter in analysis, not at runtime. The command below installs the package and records it in your composer.json. What you should see afterwards is a new dev requirement for phpstan/phpstan-strict-rules.
composer require --dev phpstan/phpstan-strict-rulesIf the project already uses phpstan/extension-installer, that is the whole setup and the rules are picked up on the next run. Without it, point your PHPStan configuration at the shipped file, using this include so the path resolves inside the vendor directory:
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neonOne point deserves attention. The README notes that besides introducing new custom rules, the package also changes the default values of some configuration parameters that exist in PHPStan itself, and those are documented on phpstan.org under stricter analysis. So installing the extension is not only a matter of adding new checks. Some existing PHPStan behaviour shifts as a side effect, which is the first thing to read about before enabling it on a large codebase.
Booleans, casts and numeric operands account for much of the rule set
A cluster of rules deals with types that PHP would otherwise leave implicit. booleansInConditions requires booleans in if, elseif, ternary operator, after the negation operator, and on both sides of the logical operators, and booleansInLoopConditions does the same for while and do while. The point is to stop a truthy string or a non-empty array from silently acting as a condition. uselessCast detects casts that change nothing, such as casting to int when the expression is already int. numericOperandsInArithmeticOperators requires numeric operands across the arithmetic set and the increment and decrement operators, which catches the case where a string is added to a number and PHP coerces it. strictFunctionCalls is the sharpest of the group, because it targets functions that already ship a strict parameter and requires it to be set to true: in_array, array_search, array_keys when a search value is given, and base64_decode. A team that has been bitten by loose in_array matching will recognise the reasoning immediately.
The rules ban PHP idioms that rely on loose comparison
Another cluster is less about types and more about which language constructs a codebase is allowed to contain. disallowedLooseComparison removes the == and != operators outright, and disallowedEmpty removes empty(), which the rule description calls a very loose comparison with a pointer to the PHP manual. disallowedShortTernary removes the short ternary because it implies weak comparison, with the null coalesce operator or a full ternary offered as the replacement. switchConditionsMatchingType requires the types in a switch condition and its case values to match, since PHP compares them loosely by default and that can lead to unexpected results. overwriteVariablesWithLoop stops foreach key and value variables and for loop initial assignments from clobbering a variable that already holds something. noVariableVariables removes the $$foo form and the equivalent dynamic method call, and disallowedImplicitArrayCreation blocks $var[] = when the variable does not exist yet. These are not bug detectors so much as a constitution for the language.
Inheritance and constructor rules police the class contract
A separate group of rules deals with class design rather than expressions. The table lists contravariance for parameter types and covariance for return types in inherited methods, described as the Liskov substitution principle, plus a variant that checks the same principle for static methods. Two more rules enforce correct case for referenced and called function names, and for inherited and implemented method names, which matters on case sensitive file systems and for autoloading. requireParentConstructorCall insists that a child constructor calls the parent one, and illegalConstructorMethodCall disallows calling __construct() on an existing object or as a static call outside of a parent constructor. closureUsesThis asks a closure to use $this directly rather than capturing it indirectly. dynamicCallOnStaticMethod checks that statically declared methods are called statically. Together these turn a set of style preferences about class shape into build failures, which is the point of the package, and also the reason it can be expensive to introduce.
Turning rules off is a per-rule configuration exercise, and allRules is the blunt instrument
Every rule in the table can be disabled individually, and the switch names match the rule names. The snippet below is the documented way to relax specific checks, for example when a legacy dependency forces loose comparison or when a parent class cannot be changed.
parameters:
strictRules:
disallowedLooseComparison: false
booleansInConditions: false
uselessCast: falseFor a project that wants only one or two strict rules, the documented approach is to set allRules to false and then re-enable what it wants. A partial set looks like this, and it is the configuration most teams should expect to end up with.
parameters:
strictRules:
allRules: falseThree rules in the table behave differently from the rest, since they report conditions that are always true: checkAlwaysTrueInstanceof, checkAlwaysTrueCheckTypeFunctionCall and checkAlwaysTrueStrictComparison. Each can be turned off with a parameter of the same name. These are the checks most likely to fire on code that is correct but redundant, and they are the first candidates for disabling in a codebase that has already been cleaned up once.
The alternative is PHPStan's own stricter analysis parameters
The honest comparison is not with another extension but with what PHPStan already offers. The README states that the package changes the default values of some configuration parameters present in PHPStan itself, documented on phpstan.org under stricter analysis. A team that wants stricter analysis but not a list of opinionated rules can therefore reach for those parameters alone, and keep the extension for the handful of checks that genuinely matter to it. The trade-off runs in both directions. The built in parameters change how PHPStan analyses your code without telling you which idioms are banned, while this package names each ban explicitly and gives every one a switch. The other difference is cost. The rules here are opinionated by design, so a mature codebase adopting them wholesale will see failures that are not bugs at all, and the work of triaging them falls on the team. The package is MIT licensed, so using it in a commercial project carries no licensing obstacle. The repository is not archived, the last push was on 2026-10-19, and the recent tags are 2.1.0 on 2026-10-06, 2.0.12 on 2026-07-19 and 2.0.11 on 2026-05-02, so the rule set is still moving.
Editorial conclusion
Adopt phpstan-strict-rules when the team wants PHPStan to enforce one strict dialect across a codebase, and expect to spend the first week turning rules off where the project has to live with legacy code. Do not add it to a project that only needs a higher analysis level, because the package also changes default values of PHPStan's own parameters. Before running it in CI, check the disabled rules list in rules.neon against the violations your pipeline already reports, since every rule here is a new failure waiting to happen.
Frequently asked questions
How do I install phpstan-strict-rules?
Require it as a development dependency with Composer, using the command composer require --dev phpstan/phpstan-strict-rules. If you also install phpstan/extension-installer the rules are registered automatically, otherwise you include vendor/phpstan/phpstan-strict-rules/rules.neon from your PHPStan configuration.
Can I enable only a few strict rules instead of all of them?
Yes. The documentation says you can disable all rules from the included rules.neon by setting allRules to false, and then turn individual rules on as needed. Every rule also has its own parameter under strictRules that can be set to false to switch that single check off.
Does phpstan-strict-rules change how PHPStan behaves on its own?
Yes. The README states that the package also changes the default values of some configuration parameters that are present in PHPStan itself, and those parameters are documented on phpstan.org under stricter analysis.
Which PHP functions does strictFunctionCalls affect?
It requires the strict parameter of certain functions to be set to true: in_array, array_search, array_keys when a search value is provided, and base64_decode. The rule exists because those functions contain a strict parameter for better type safety.
What licence is phpstan-strict-rules under?
The package is MIT licensed. The repository is not archived, the last push was on 2026-10-19, and recent releases include 2.1.0 on 2026-10-06, 2.0.12 on 2026-07-19 and 2.0.11 on 2026-05-02.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/phpstan-phpstan-strict-rules)Was this useful?