Skip to content

Code quality tools

We are using some tools to monitor our code quality and to enforce follow to our coding standards. All of them are installed to our project (usually as dev dependencies) or available in our Docker container with an idea to make developer’s life easier.

Our CI already has a good setup to run these tools automatically on some events. This document will answer to how and when to run these tools locally.

Use local PHP version to run them faster

If you have PHP installed locally, you can run these tools faster than in Docker. Docker can use only a limited number of your CPU cores, while locally installed PHP can use all of them.

Static analysis

Psalm

Psalm is our main PHP static analyser. Runs on CI on every push if there are any changes in PHP files.

To run it locally (faster), use

sh
composer psalm

to run on Docker (pls use aliases):

sh
docker compose exec app composer psalm

When to run locally: on major changes in PHP files before pushing to the main branch (e.g., method signature changes, new methods, etc.)

Other commands:

  • composer psalm:baseline:update to update the baseline file by removing already solved issues.
  • composer psalm:baseline:regenerate to completely regenerate a baseline file. Usually needed when you want to add a lot of suppressions for Psalm’s reports. Please always review changes in the baseline file before committing them.

Psalm supports a lot of docblock annotations that may help analysis a lot:

Advanced Psalm is configured to send stats on every release to Google Spreadsheets:

PHPStan

PHPStan is a static analysis tool very similar to Psalm. Sometimes it can find issues that Psalm cannot find (and vice versa); that’s why we use both of them. Unlike Psalm, CI runs PHPStan only on new PRs and Releases (to minimize price we pay for GitHub actions).

Commands:

  • composer phpstan to install/update and run.
  • composer phpstan:run to run it.
  • composer phpstan:baseline:regenerate to completely regenerate baseline file. PHPStan doesn’t have an option to remove only solved issues from baseline; this is the only easy way to clean up baseline file from them.

PHPStan automatically uses config stored in the repo.

When to run locally: similar to Psalm: on important API or PHP types changes.

Rector

Rector is a CLI tool written in PHP. It can instantly upgrade old PHP code and handle automated refactorings.

We use it in 2 different cases:

  • On CI to automate some code optimisations
  • On code migration: e.g., on updating PHP, Laravel or PHPUnit versions

Commands:

  • composer rector to run it on our codebase using config stored un the repo. It will automatically optimize codebase. After running this command, you need to run coding style fixers as Rector knows nothing about our coding styles.

When to run locally: on PHP or Laravel upgrades; on mass code changes (e.g. a big PR)

Coding style checks

We use 2 tools to check and fix our coding style. And there is a single command to run them all:

sh
composer cs

cs stands for coding style.

When to run locally: CI will run it automatically on every push and commit changes to your branch. Thus, run it manually only if you want to avoid extra commits.

Normally, you just need to remember this command, but in this guide we'll describe each tool separately in details.

PHP CS Fixer

It’s less advanced than PHP Code Sniffer but has 2 important benefits:

  • it can fix all issues automatically
  • it’s a way faster when cache is available

How to run:

sh
composer php-cs-fixer

When to run locally: almost never: it’s CI’s job to fix coding style issues.

PHP Code Sniffer

We have some code-standard rules/conventions based on PER-CS 2.0 rules. PHP Code Sniffer is a tool that checks our code for code-standard violations - here is a config (which is based on our shared config https://github.com/InteractionDesignFoundation/coding-standard).

Advanced usage
sh
# check all project
phpcs

# check only one file
phpcs app/Models/Billing/Invoice.php

# check directory
phpcs app/Models/Billing

output example (with error):

text
FILE: /database/migrations/2015_10_08_021947_make_member_id_nullable_on_notifier_logs.php
---------------------------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
---------------------------------------------------------------------------------------------------------------
 6 | ERROR | Each class must be in a namespace of at least one level (a top-level vendor name)
---------------------------------------------------------------------------------------------------------------

Time: 6.34 secs; Memory: 24Mb

PHP Code Beautifier

Some errors can be fixed automatically by PHP Code Beautifier that ships with PHP Code Sniffer. This tool has almost the same command line options and arguments, but you can simply use it without them:

sh
# fix all files in project
phpcbf

# fix only one file
phpcbf app/Models/Billing/Invoice.php

# fix files in directory
phpcbf app/Models/Billing

Official documentation: PHP_CodeSniffer wiki

There is a composer command that runs both phpcbf and php-cs-fixer:

sh
composer cs:fix

There are 2 types of issues that PHP Code Sniffer can find:

  • automatically fixable
  • not automatically fixable

Our CI script will always try to fix issues automatically. If it can’t fix them, it will fail the build.

When to run locally: when CI can’t fix issues automatically.

Deptrac

Deptrac helps keep application architecture clean by dividing it into architectural layers over classes and specifying which rules should apply to them.

Examples:

  • forbid using Request in a Model;
  • forbid using Controllers in Console Commands.

How to run:

sh
# install deptrac and run it:
composer deptrac
# or just run if you already downloaded it recently:
composer deptrac:run

When to run locally: if you are not sure about interlayer changes you made.