PHP: Psaml
Antonio Silva
Posted on October 9, 2023
About Psalm
Psalm is a static analysis tool for finding errors in PHP applications.
It has a few features that go further than other similar tools:
-
Mixed type warnings
If Psalm cannot infer a type for an expression then it uses a
mixed
placeholder type.mixed
types can sometimes mask bugs, so keeping track of them helps you avoid a number of common pitfalls. -
Intelligent logic checks
Psalm keeps track of logical assertions made about your code, so
if ($a && $a) {}
andif ($a && !$a) {}
are both treated as issues. Psalm also keeps track of logical assertions made in prior code paths, preventing issues likeif ($a) {} elseif ($a) {}
. -
Property initialisation checks
Psalm checks that all properties of a given object have values after the constructor is called.
-
Taint analysis
Psalm can detect security vulnerabilities in your code.
-
Language Server
Psalm has a Language Server that’s compatible with a range of different IDEs.
-
Automatic fixes
-
Automatic refactoring
Psalm can also perform simple refactors from the command line.
Installation
The latest version of Psalm requires PHP >= 7.4 and Composer.
composer require --dev vimeo/psalm
Generate a config file:
./vendor/bin/psalm --init
Psalm will scan your project and figure out an appropriate error level for your codebase.
Run psalm for entire project:
./vendor/bin/psalm
Or for specific files:
./vendor/bin/psalm src/Controller
Save results in XML:
./vendor/bin/psalm --report=checkstyle.xml
Psalm will probably find a number of issues - find out how to deal with them in Dealing with code issues.
Error levels
You can run Psalm in at different levels of strictness from 1 to 8.
Level 1 is the most strict, level 8 is the most lenient.
When no level is explicitly defined, psalm defaults to level 2.
Some issues are always treated as errors. These are issues with a very low probability of false-positives.
At level 1 all issues (except those emitted for opt-in features) that Psalm can find are treated as errors. Those issues include any situation where Psalm cannot infer the type of a given expression.
At level 2 Psalm ignores those Mixed* issues, but treats most other issues as errors.
At level 3 Psalm starts to be a little more lenient. For example Psalm allows missing param types, return types and property types.
At level 4 Psalm ignores issues for possible problems. These are more likely to be false positives – where the application code may guarantee behaviour that Psalm isn't able to infer.
Level 5 and above allows a more non-verifiable code, and higher levels are even more permissive.
Dealing with code issues
Psalm has a large number of code issues. Each project can specify its own reporting level for a given issue.
Code issue levels in Psalm fall into three categories:
-
error
This will cause Psalm to print a message, and to ultimately terminate with a non-zero exit status.
-
info
This will cause Psalm to print a message.
-
suppress
This will cause Psalm to ignore the code issue entirely.
Basic Usage
./vendor/bin/psalm --init scr/ 8
The first parameter tells Psalm where to find our source code, and the second is the strictness level.
./vendo/bin/psaml file.php
Target PHP version: 8.2 (inferred from current PHP version).
Scanning files...
Analyzing files...
E
ERROR: UnusedClass - index.php:3:8 - Class User is never used (see https://psalm.dev/075)
class User{
ERROR: MissingConstructor - index.php:4:18 - User has an uninitialized property User::$name, but no constructor (see https://psalm.dev/073)
private string $name;
ERROR: MissingConstructor - index.php:5:19 - User has an uninitialized property User::$products, but no constructor (see https://psalm.dev/073)
private array $products;
ERROR: MissingReturnType - index.php:7:21 - Method User::Add does not have a return type, expecting void (see https://psalm.dev/050)
public function Add(){
ERROR: MixedAssignment - index.php:8:6 - Unable to determine the type that $this->name is being assigned to (see https://psalm.dev/032)
$this->name = $name;
ERROR: UndefinedVariable - index.php:8:20 - Cannot find referenced variable $name (see https://psalm.dev/024)
$this->name = $name;
------------------------------
6 errors found
------------------------------
Psalm can automatically fix 1 of these issues.
Run Psalm again with
--alter --issues=MissingReturnType --dry-run
to see what it can fix.
------------------------------
The analysis report resulted in 6 errors and 1 of them can be fixed automatically.
Automatically fixing errors:
./vendor/bin/psalm --alter --issues=MissingReturnType file.php
Target PHP version: 8.2 (inferred from current PHP version).
Scanning files...
Analyzing files...
░
Altering files...
Altered /home/zero/Documents/Linguagens/PHP/Psaml/index.php
------------------------------
No errors found!
------------------------------
Sometimes this may appear in the report:
------------------------------
10 other issues found.
You can hide them with --show-info=false
------------------------------
It did find 10 other issues, reported as INFO lines in the output. Anything reported as INFO at a lower strictness level gets reported as an error at higher strictness levels, because we plan on working up through the strictness its safe for us to ignore these INFO issues.
To not show the INFO:
./vendor/bin/psalm --show-info=false file.php
To show the INFO:
./vendor/bin/psalm --show-info=true file.php
Posted on October 9, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
April 18, 2023