What is Static Analysis

Static analysis (static code analysis or source code analysis) applies a set of coding rules to debug source code before a program is run. Applied in the early phase of code development, the goals of static analysis are:

  • Catch and fix errors like type-related errors which can occur especially in dynamically-typed programming languages like PHP.
  • Confirm coding standards to ensure readability and maintainability for large projects that need a consistent coding style.
  • Identify code that needs refactoring and recommend improvements to improve complex or ‘smelly’ code.
  • Enhance security by detecting potential code injection in PHP, cross-site scripting (XSS) and open redirect vulnerabilities.

The top static analysis tools are:

  • PHPStan
  • Psalm
  • Snyk
  • Sonarqube
  • Scrutinizer
  • PHPCheckstyle

Why Switch from Psalm to PHPStan?

Dotkernel has been using psalm for a while now and the results have always been positive. A large part of the PHP community, especially developers in widely-used projects like Doctrine and Composer, have opted for PHPStan instead. For most use cases, psalm and PHPStan have identical findings, so it isn’t really justified to use both.

PHPStan has some advantages to psalm:

  • A faster growing ecosystem.
  • Better social media presence.
  • A fulltime contributor (author @ondrejmirtes).
  • Uses PHP stubs from PHPStorm.
  • Better quality and depth of detection.

Thus, the better choice becomes PHPStan.

Updating Your Project to Use PHPStan

First, remove the references to psalm

  • update the require in your composer.json file
    • remove vimeo/psalm
    • add these packages
      • “phpstan/phpstan”: “^2.0”
      • “phpstan/phpstan-doctrine”: “^2.0”
      • “phpstan/phpstan-phpunit”: “^2.0”,
  • update the scripts in your composer.json file
    • replace "static-analysis": "psalm --shepherd --stats", with "static-analysis": "phpstan analyse --memory-limit 1G",
  • run composer update to install the new packages
  • delete psalm-baseline.xml and psalm.xml
  • create file .github/workflows/static-analysis.yml with the content below to configure the environment and the steps for PHPStan
on:
  - push

name: Run PHPStan checks

jobs:
  mutation:
    name: PHPStan ${{ matrix.php }}-${{ matrix.os }}

    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os:
          - ubuntu-latest

        php:
          - "8.2"
          - "8.3"

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: "${{ matrix.php }}"
          coverage: pcov
          ini-values: assert.exception=1, zend.assertions=1, error_reporting=-1, log_errors_max_len=0, display_errors=On
          tools: composer:v2, cs2pr

      - name: Determine composer cache directory
        run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV

      - name: Cache dependencies installed with composer
        uses: actions/cache@v4
        with:
          path: ${{ env.COMPOSER_CACHE_DIR }}
          key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
          restore-keys: |
            php${{ matrix.php }}-composer-
      - name: Install dependencies with composer
        run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi

      - name: Setup project
        run: |
          mv config/autoload/local.php.dist config/autoload/local.php
          mv config/autoload/mail.local.php.dist config/autoload/mail.local.php
          mv config/autoload/local.test.php.dist config/autoload/local.test.php
      - name: Run static analysis with PHPStan
        run:  vendor/bin/phpstan analyse
  • create the file phpstan.neon with the content below to configure the extensions, the rule level and the ignore rules
includes:
    - vendor/phpstan/phpstan-doctrine/extension.neon
    - vendor/phpstan/phpstan-phpunit/extension.neon
parameters:
    level: 5
    paths:
        - src
        - test
    treatPhpDocTypesAsCertain: false
    ignoreErrors:
        -
            message: '#Call to an undefined method.*setAllowOverride#'
            path: test/Functional/AbstractFunctionalTest.php

Running the PHPStan checks

To run the checks, use this command:

composer static-analysis

composer.json is currently set up to run this command which sets up the memory limit to a higher amount that that from the php.ini file in PHP (128M).

vendor/bin/phpstan analyse --memory-limit 1G 

If you still get the error below, try increasing the memory limit further, e.g. 2G or 4G.

Child process error: PHPStan process crashed because it reached configured PHP memory limit: 128M

Summary

In this article we revisited the theoretical meaning of static analysis and focused on the change from psalm to PHPStan. It’s highly recommended to use a static analysis tool in your project and, while both psalm and PHPStan perform similar functions, the latter has recently stepped ahead of the former.


Looking for PHP, Laminas or Mezzio Support?

As part of the Laminas Commercial Vendor Program, Apidemia offers expert technical support and services for:

  • Modernising Legacy Applications
  • Migration from any version of Zend Framework to Laminas
  • Migration from legacy Laminas API Tools (formerly Apigility) to Dotkernel API
  • Mezzio and Laminas Consulting and Technical Audit
  • Leave a Reply

    Your email address will not be published. Required fields are marked *

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>