PHPStan and Psalm

Contents
Install
Simple example
Complex usage
What it found in src/

Install

Nothing to install by hand. The first run downloads phpstan.phar and psalm.phar into ~/.cache/aredel-tools/ and executes them under the php:8.2-cli image. Psalm gets a minimal config generated per run — no psalm.xml is added to the repo. Versions on this site: PHPStan 2.2.14, Psalm 6.18.0:

./scripts/lint-static.sh --tool phpstan --files src/dev/php/linters/phpstan_psalm.php ./scripts/lint-static.sh --tool psalm --files src/dev/php/linters/phpstan_psalm.php

Simple example

PHPStan is the default tool — analyse one file for unknown symbols, bad types and dead code:

./scripts/lint-static.sh --files src/ru/qa/.php/BasePage.php

Second opinion from Psalm (missing types, unused code):

./scripts/lint-static.sh --tool psalm --files src/ru/qa/.php/BasePage.php

Complex usage

Both tools at once, strictness ladder, staged-only checks, and a saved report:

./scripts/lint-static.sh --tool phpstan,psalm,phpcs --files src/ru/qa/.php/ ./scripts/lint-static.sh --tool phpstan --level 2 --files src/ru/qa/.php/ ./scripts/lint-static.sh --tool psalm --staged ./scripts/lint-static.sh --tool phpstan --files src/ru/qa/.php/ --report reports/phpstan-qa

Practical loop on legacy code: narrow the scope (--files / --staged), fix new code first, raise --level 0-9 only when the current level is quiet. Reports append .txt when missing and start with a UTC timestamp; the exit code still reflects the tools, not the report.

What it found in src/

Expect findings on legacy files — that is normal, not a reason to fix everything at once:

  1. PHPStan level 1 flags dynamic properties (Access to an undefined property): page classes assign $this->... without declaring them, which PHP 8.2 deprecates. The new BasePage and ArticlePage classes already declare every property for exactly this reason.
  2. Cross-file unknowns when files are analysed standalone — pass a whole directory so symbols resolve.
  3. Psalm additionally wants return types everywhere (MissingReturnType) and reports unused code.

Unlike PHPCS, neither tool auto-fixes: every finding is a human decision. That is why style went first in the src/ cleanup (3533 down to 695 PHPCS violations) and bug-hunting with these two is next.

Article author: Andrei Olegovich

Related articles
Development with PHP
PHP linters we use
php -l and lint-php.sh
PHPCS: PHP CodeSniffer
phpcs.xml ruleset file
PHPCBF: fix style automatically
wrap-long-lines.sh
PHPStan and Psalm

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.ru
Write to info@urn.su if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: