Due to Psalm’s lack of support for being installed with PHP 8.4 or PHPUnit 11 at the time (January 15, 2025, prior to the Psalm 6.0 release), I finally gave PHPStan a try.
The big difference that has caused the most trouble is that PHPStan wants iterable/container types to explicitly document their contents. Any time a method returns array
, PHPStan wants to know, array of what? Psalm was happy to observe what the method put in the array for return, and use that de facto type as the developer’s intention.
Outside of the smallest library repositories, that rule got ignored. It is responsible for maybe 75% of issue reports. If I can take it from 1200 down to 275 with a single ignore, that is the difference between “there are too many things to deal with” and “I can make a dent in this today.”
The next obvious difference has been that PHPStan is much more interested in handling the potential false
returned from preg_replace('/\\W+/', '', $str);
calls. Psalm expected that giving three string arguments to preg_replace()
will always result in a string of some sort.
There’s also a class of issues reported by PHPStan due to a disagreement in the other direction. Psalm seemed to think that number_format()
returned string|false
, requiring an is_numeric()
check on the variable. PHPStan thinks that is redundant, i.e. that number_format()
has already returned a numeric-string.
I don’t have a sense yet for how effective PHPStan is at finding problems overall. In code that was previously checked with Psalm, many defects visible to static analysis have already been removed, leaving little fruit behind for PHPStan to pick.
As of early February, PHPStan can be considered a successful migration. I haven’t touched PHPStan Pro, but I may try it if I ever want to fix those hundreds of issues with array
types.