Yii2 application static analysis with Psalm

by George Cadwallader
Practically has developed a Psalm Yii2 plugin as a static analyser for making sure your object types are refined and defined.
Jul 27, 2021

Psalm is an excellent tool for static analysis of a codebase. It is generally used to find type inconsistencies in your application, and has become especially useful with the introduction of more consistent and strict type safety in PHP stating with version 7.1.

Each release gives us more and more options to add types to our applications. Unfortunately, It’s not so easy to just type cast our applications. If we were to go and add type or all of your return function and class properties, our application will start to throw hard exceptions where they were working before.

1
2
3
4
function test($param) {
    return $param;
}
test('5');

The following snippet of code is not an uncommon occurrence in a PHP application. Using an int as a string is something that has always worked. However, with newer versions of PHP, you will get a fatal PHP exception.

1
2
3
4
5
function test(int $param): int {
    return $param;
}
 
test('5');

It is unrealistic for the maintainer of applications to go and type their application and fix all the errors in one update. This is where Psalm comes in. Psalm is a static analysis tool that will catch type issues. It will work by using type hints or doc comments. This is where the power of Psalm makes developer’s life so much easier.

1
2
3
4
5
6
7
8
9
10
/**
 * @param int $param
 *
 * @return int
 */

function test($param) {
    return $param;
}
 
test('5');

The above code is now type cast, meaning Psalm will throw an error, however the production code will still run without throwing exceptions. This makes the move to a typed codebase more of a migration, not an upgrade. You can slowly refactor your code making it more type safe without impacting the production code.

It doesn’t take a developer to say that this is a godsend for huge development projects that are already live and running.

Here at Practically we use Yii2 for a lot of our projects. The way Psalm works is that it reads function definitions and class doc blocs to figure out the types of symbols in your application. Yii2 has two problematic design patterns that make it difficult and tedious to type an application.

BaseObject

The yii2 base object uses magic getters and setters to access properties through functions based on a naming convention. If you have a function “getName” you can access the property “name” via the PHP magic method “__get”. The issue with this is that property “name” doesn’t exist, so psalm has no way of knowing what it is.

Models

Models in yii2 have properties based on the fields in the database. If you have a field called “username” in your database, you will have a property on that model called “username”. Again, the issue is that this type doesn’t exist in the codebase and psalm has no way of knowing what it is.

The solutions

The main and obvious solution of this is to document the code, so psalm can pick up the types. And yes, this is the way you should probably do it. The main advantage to this is you get better IDE support.

Due to the number of applications we run here at Practically.io – many small by industry standards –  we chose to create a Psalm plugin for Yii2 to gradually migrate to this new methodology. Firstly, we want to give a big shout out to the developers of the Laravel plug-in, this was a big influence on how we created ours. The yii2 plugin currently adds stubs to tell Psalm about some return types and fill in some inconsistencies. It will also automatically resolve property names from the getters and setters of classes. This prevents developers from having to go through the application and add all the missing types to get the advantage of type safety.