PHP: Psaml

Antonio Silva - Oct 9 '23 - - Dev Community

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) {} and if ($a && !$a) {} are both treated as issues. Psalm also keeps track of logical assertions made in prior code paths, preventing issues like if ($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

    Psalm can fix many of the issues it finds automatically.

  • 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
Enter fullscreen mode Exit fullscreen mode

Generate a config file:

./vendor/bin/psalm --init
Enter fullscreen mode Exit fullscreen mode

Psalm will scan your project and figure out an appropriate error level for your codebase.

Run psalm for entire project:

./vendor/bin/psalm
Enter fullscreen mode Exit fullscreen mode

Or for specific files:

./vendor/bin/psalm src/Controller
Enter fullscreen mode Exit fullscreen mode

Save results in XML:

./vendor/bin/psalm --report=checkstyle.xml
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The first parameter tells Psalm where to find our source code, and the second is the strictness level.

./vendo/bin/psaml file.php
Enter fullscreen mode Exit fullscreen mode
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.
------------------------------
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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!       

------------------------------

Enter fullscreen mode Exit fullscreen mode

Sometimes this may appear in the report:

------------------------------
10 other issues found.
You can hide them with --show-info=false
------------------------------
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

To show the INFO:

./vendor/bin/psalm --show-info=true file.php
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .