Static code analysis in PHP (and GitLab)

Jan 12, 2020 by Thibault Debatty | 6337 views

PHP GitLab Secure Software Development

https://cylab.be/blog/51/static-code-analysis-in-php-and-gitlab

In the PHP toolbox for testing, you'll often find phpunit for unit testing, PHP_CodeSniffer for code style analysis, and here we present PHPStan for static code analysis.

Static code analysis tries to detect bugs by analyzing the source code of a program, without actually running it. At the opposite of PHPUnit, you don't need to write tests for your app.

In my opinion, static code analysis is particularly useful for an interpreted language like PHP, as it allows to detect "compile" errors in edge cases that are not covered by a unit test.

In the example below, PHPStan will immediately detect the missing `````` in front of Exception(...). With PHPUnit this would require an additional test to cover this single line of code:

namespace App;

class Foe
{
    public function bar() {
        $r = $this->doSomething();
        if ($r == null) {
            throw new Exception("Failed to do something...");
        }
    }
}

Installation and usage

PHPStan is best installed with composer:

composer require --dev phpstan/phpstan

You can run PHPStan directly from the command line, by using the command analyze and listing the directories to process:

vendor/bin/phpstan analyse src tests

However, it's easier to create a configuration file called phpstan.neon so you can omit the list of directories:

includes:
parameters:
  level: 1
  paths:
    - src
    - tests
  excludes_analyse:
  ignoreErrors:
  reportUnmatchedIgnoredErrors: false

The configuration file uses neon syntax, which is actually very similar to YAML.

Levels

As you can see in the configuration file, PHPStan has a configurable level for the analysis. In a nutshell, here is what each level will check:

  • level 0 : parse errors
  • level 1 : undefined variables
  • level 2 : correct type hints (but does not enforce the presence of type hints, see level 6)
  • level 3 : correct type of return values
  • level 4 : comparisons
  • level 5 : correct type of method parameters
  • level 6 : presence of type hints
  • level 7 : null returned values

The complete list of tests for each level is available on the GitHub page of PHPStan.

Integration in GitLab

To run phpstan at each push to GitLab, simply add this job to your .gitlab-ci.yml:

test:phpstan:
  image: cylab/php72
  before_script:
    - COMPOSER_CACHE_DIR=composer-cache composer install
  script:
    - vendor/bin/phpstan analyse

Additional rules

It is also possible to run additional rules in PHPStan. For example, to check for deprecated classes and methods, simply install the appropriate package:

composer require --dev phpstan/phpstan-deprecation-rules

Then add the rules to the includes section of your phpstan.neon:

includes:
    - vendor/phpstan/phpstan-deprecation-rules/rules.neon

PHPDoc

PHPStan takes advante of PHPDoc type annotations to derive parameters and return types. For example:

    /**
     * @param string $name
     * @return void
     */
    public function sayHello($name)
    {
    }

Here are the most common PHPDoc types:

  • int, integer
  • string
  • array-key
  • bool, boolean
  • true, false
  • null
  • float, double, scalar
  • array
  • iterable
  • callable
  • resource
  • void
  • object

Any class or interface can be used as a PHPDoc type. Finally, you can define the type as an array of other type:

  • Type[]
  • array<Type>
  • array<int, Type>
  • non-empty-array<Type>
  • non-empty-array<int, Type>

You can find the full list of PHPStan: https://phpstan.org/writing-php-code/phpdoc-types

This blog post is licensed under CC BY-SA 4.0

This website uses cookies. More information about the use of cookies is available in the cookies policy.
Accept