Skip to main content
Problem matchers are JSON configuration files that tell GitHub Actions how to parse tool output and surface errors and warnings as inline annotations directly in pull requests and workflow run logs. They map log patterns to file paths and line numbers so reviewers can see issues without leaving the diff. setup-php ships problem matcher files for PHP and PHPUnit inside the runner’s tool cache. Additional tools like PHPStan and Psalm have native GitHub Actions output formats that work without a separate matcher file.

PHP

The PHP problem matcher catches fatal errors, parse errors, and warnings in PHP output and links them to the corresponding source file and line. Add this step immediately after the setup-php step:
- name: Setup problem matchers for PHP
  run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"

PHPUnit

The PHPUnit problem matcher highlights failing test cases in the workflow run log and annotates the test file at the failing assertion’s line number. Add this step after the setup-php step, before you run your tests:
- name: Setup problem matchers for PHPUnit
  run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
You can activate both matchers in a single workflow to get annotations for both PHP runtime errors and PHPUnit failures.

PHPStan

PHPStan has native GitHub Actions support built in. When it detects that it is running inside GitHub Actions it automatically emits annotations without requiring a problem matcher. No additional configuration is needed.
- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: '8.5'
    tools: phpstan

- name: Run PHPStan
  run: phpstan analyse src

Psalm

Psalm supports GitHub Actions output via the --output-format=github flag. This emits annotations for every issue Psalm finds.
- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: '8.5'
    tools: psalm

- name: Run Psalm
  run: psalm --output-format=github

Tools with checkstyle support

Several PHP tools can emit results in the checkstyle XML format: phpcs, phpstan, psalm, and php-cs-fixer. You can pipe that output into cs2pr, which converts checkstyle XML into GitHub Actions annotations. Install cs2pr via the tools input and pipe checkstyle output to it:
- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: '8.5'
    tools: cs2pr, phpcs

- name: Run phpcs
  run: phpcs -q --report=checkstyle src | cs2pr
- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: '8.5'
    tools: cs2pr, php-cs-fixer

- name: Run php-cs-fixer
  run: php-cs-fixer fix --dry-run --format=checkstyle | cs2pr
- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: '8.5'
    tools: cs2pr, phpstan

- name: Run PHPStan
  run: phpstan analyse --error-format=checkstyle src | cs2pr
- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: '8.5'
    tools: cs2pr, psalm

- name: Run Psalm
  run: psalm --output-format=checkstyle | cs2pr
cs2pr exits with a non-zero status code when it finds issues, which causes the workflow step to fail as expected. Refer to the cs2pr documentation for additional options such as filtering by severity or graceful-warnings mode.

Combining matchers in a workflow

The example below shows a complete workflow that activates both the PHP and PHPUnit problem matchers alongside PHPStan’s native annotations:
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.5'
          extensions: mbstring
          tools: phpstan
          coverage: xdebug

      - name: Setup problem matchers for PHP
        run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"

      - name: Setup problem matchers for PHPUnit
        run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

      - name: Install Composer dependencies
        run: composer install --no-progress --prefer-dist

      - name: Run PHPStan
        run: phpstan analyse src

      - name: Run tests
        run: vendor/bin/phpunit --coverage-text

Build docs developers (and LLMs) love