Making PHPStan, Psalm and PHP_CodeSniffer Work Directly in PhpStorm
AI generated
IDE
{ }
PhpStorm · PHPStan · Psalm · PHP_CodeSniffer
PHPStan, Psalm and PHPCS
working directly in PhpStorm

Seeing static analysis and code style checks for the first time in the CI pipeline is too late. PHPStan, Psalm and PHP_CodeSniffer can be integrated directly into PhpStorm, as External Tools, Run Configurations and File Watchers, so feedback arrives the moment you save, not only at the pull request.

18 min read PHPStan · Psalm · PHPCS · External Tools · File Watchers PhpStorm 2024+ · PHP 8.x · Composer

1. Why local integration is worthwhile at all

The typical workflow without local integration looks like this: developers write code, push it, the CI pipeline runs, and ten minutes later an email arrives with PHPStan errors. That is wasted time, for the developer who has already switched context, and for the pipeline, which ran unnecessarily. Integrating PHPStan, Psalm and PHP_CodeSniffer into PhpStorm means shrinking this feedback cycle from minutes to seconds.

PhpStorm ships with its own inspections that show PHP errors, type problems and code style violations directly in the editor. These inspections, however, are not the same as a full PHPStan run at level 8 or Psalm with strict typing. The IDE's own checks are fast and incremental, while external tools like PHPStan analyze the entire call graph, know types from phpstan.neon stubs, and catch errors PhpStorm cannot see. Both approaches complement each other, and that exact combination is the goal of this article.

Another reason for local integration: PHPCS with project-specific rulesets (for example the Magento Coding Standard) formats code consistently before it ever reaches review. PHPCBF, the automatic fixer that ships with PHPCS, can be run directly from PhpStorm as an External Tool call and corrects most style violations without manual intervention.

2. Setting up PHPStan as an External Tool in PhpStorm

The first step is installing PHPStan via Composer. For projects with a Docker environment, such as the Mark Shust setup for Magento, PHPStan runs inside the container. PhpStorm supports exactly this use case through External Tools with a configured PHP interpreter that points at the container.

In PhpStorm you open Settings → Tools → External Tools and create a new tool. As the program you enter the path to the PHP interpreter (or the Docker wrapper), and as arguments the path to vendor/bin/phpstan followed by analyse --no-progress $FilePath$. The macro $FilePath$ passes the currently open file. With $ProjectFileDir$ as the Working Directory, PHPStan always runs in the correct context. The result appears in the tool window, and double-clicking an error message jumps straight to the corresponding line.


# phpstan.neon, project configuration in the project root
parameters:
    level: 8
    paths:
        - src/app/code
    excludePaths:
        - src/vendor
        - src/generated
    # Magento-specific extensions
    bootstrapFiles:
        - phpstan-bootstrap.php
    ignoreErrors:
        # Known false positives on Magento proxies
        - '#Call to an undefined method [a-zA-Z0-9\\_]+Proxy::#'
    # Enable PHP 8.4 features
    phpVersion: 80400
    checkMissingIterableValueType: false

services:
    -
        class: PHPStan\Rules\Classes\InstantiationRule
        tags:
            - phpstan.rules.rule

For fast execution on a single file, create a shortcut for the External Tool in PhpStorm under Settings → Keymap. That way PHPStan can be run on the current file with a single keystroke, without switching to a terminal. Important: set the --memory-limit parameter when the project is large. PHPStan can run into OOM territory on Magento codebases with many classes.

3. Integrating Psalm: differences from PHPStan and shared configuration

Psalm and PHPStan solve similar problems but have different strengths. Psalm is particularly good at catching nullability errors, has a more refined type system with template types, and offers Psalter, an automatic fixer for many of the problems it finds. PHPStan, on the other hand, is often faster and has a larger ecosystem of extensions for frameworks such as Magento or Laravel.

Integration into PhpStorm mirrors PHPStan: an External Tool under Settings → Tools → External Tools, the program pointing at the PHP interpreter or Docker wrapper, and arguments vendor/bin/psalm --output-format=emacs $FilePath$. The emacs output format produces lines in a format PhpStorm can parse and display as clickable error messages, provided you configure the matching regex under Output Filters: $FILE_PATH$:$LINE$:$COLUMN$: $MESSAGE$.


<?xml version="1.0"?>
<!-- psalm.xml, project configuration -->
<psalm
    errorLevel="3"
    resolveFromConfigFile="true"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="https://getpsalm.org/schema/config"
    xsi:schemaLocation="https://getpsalm.org/schema/config
        vendor/vimeo/psalm/config.xsd"
    findUnusedVariablesAndParams="true"
    checkForThrowsDocblock="false"
>
    <projectFiles>
        <directory name="src/app/code" />
        <ignoreFiles>
            <directory name="src/vendor" />
            <directory name="src/generated" />
        </ignoreFiles>
    </projectFiles>

    <!-- Stubs for Magento classes Psalm does not know -->
    <stubs>
        <file name="psalm-stubs/magento-facades.phpstub" />
    </stubs>

    <!-- Psalm plugins -->
    <plugins>
        <pluginClass class="Psalm\PhpUnitPlugin\Plugin" />
    </plugins>
</psalm>

In projects where both PHPStan and Psalm are used, it is worth maintaining the baseline files separately and configuring the CI pipeline so that both tools cover different parts of the codebase: Psalm on the application's own code at a strict level, PHPStan across the whole project with a sensible baseline for existing issues.

4. PHP_CodeSniffer: PHPCS and PHPCBF in PhpStorm

PhpStorm has native integration for PHP_CodeSniffer under Settings → PHP → Quality Tools → PHP_CodeSniffer. There you enter the path to the phpcs binary and choose the standard or ruleset. Once the integration is active, PhpStorm shows PHPCS warnings directly as inspections, with the same yellow and red squiggly underline as its own errors. This is the most direct form of integration and avoids the detour through a separate tool window.

For Magento projects, the Magento Coding Standard ruleset, installed via Composer, is the one to use. The phpcs.xml file in the project root defines which paths are checked and which rules apply. PhpStorm reads this configuration automatically when it sits in the project root.


<?xml version="1.0"?>
<!-- phpcs.xml, PHPCS configuration for a Magento project -->
<ruleset name="Mironsoft">
    <description>Coding standard for the Mironsoft Magento project</description>

    <!-- Paths to check -->
    <file>src/app/code</file>
    <file>src/app/design/frontend/Mironsoft</file>

    <!-- Exclusions -->
    <exclude-pattern>*/vendor/*</exclude-pattern>
    <exclude-pattern>*/generated/*</exclude-pattern>
    <exclude-pattern>*/Test/*</exclude-pattern>

    <!-- Magento Coding Standard -->
    <rule ref="Magento2">
        <!-- Disable rule that collides with PHP 8.4 -->
        <exclude name="Magento2.Annotation.MethodAnnotationStructure"/>
    </rule>

    <!-- PSR-12 additions -->
    <rule ref="PSR12">
        <exclude name="PSR12.Files.FileHeader"/>
    </rule>

    <!-- PHP version -->
    <config name="php_version" value="80400"/>

    <!-- Characters per line -->
    <rule ref="Generic.Files.LineLength">
        <properties>
            <property name="lineLimit" value="120"/>
            <property name="absoluteLineLimit" value="0"/>
        </properties>
    </rule>
</ruleset>

PHPCBF, the automatic fixer, can also be set up as an External Tool. That makes it possible to correct the current file automatically with a shortcut. In the External Tool configuration: program pointing at the PHP interpreter, arguments vendor/bin/phpcbf $FilePath$, and enable "Synchronize files after execution" so PhpStorm immediately reloads the corrected file. That way most PHPCS violations get fixed without ever touching the file by hand.

5. File Watchers: checking automatically on save

File Watchers in PhpStorm monitor file changes and automatically run a command as soon as a file is saved. The plugin has been natively integrated since PhpStorm 2023.2 and lives under Settings → Tools → File Watchers. For PHPCS a File Watcher is a natural fit: it runs PHPCBF the moment a PHP file is saved and corrects style violations. Important: restrict the scope to app/code and app/design, never apply it to vendor.

For PHPStan, I would not recommend a File Watcher. The analysis takes too long for on-save feedback and would block the cursor too often. Use a Run Configuration or an External Tool with a shortcut instead. PHPCS, by contrast, is fast enough for automatic execution and benefits considerably from File Watcher integration.

6. Run Configurations for fast analysis runs

Run Configurations under Run → Edit Configurations are well suited for analysis runs that combine multiple tools or apply to the whole project. A Compound Run Configuration starts several configurations one after another or in parallel, for example PHPCS across the whole path first, then PHPStan at level 6. The result of each configuration appears in its own tab in the Run window.

For Docker-based projects (Mark Shust setup), create Run Configurations of the Shell Script type and call the wrapper scripts: bin/phpcs, bin/phpstan or bin/analyse. That guarantees the tools run inside the container with the correct PHP version and the correct environment variables, rather than locally with a different PHP version.

7. Combining PHPStan, Psalm and PHPCS sensibly

Running all three tools on the same code at the same time can make sense, but it has to be organized so it does not cause confusion. A proven split: PHPCS runs on save via a File Watcher and deals exclusively with formatting and code style. PHPStan runs via a Run Configuration or a shortcut on the current file and delivers type feedback. Psalm runs in the CI pipeline and on your own code at the pre-commit hook, not constantly locally.

Redundancy between PHPStan and PhpStorm's own inspections is unavoidable. Both find type errors, but PHPStan knows the project-specific stubs and extensions that PhpStorm does not. Instead of disabling PhpStorm's inspections, it is better to leave them at a lower severity level and treat PHPStan as the authoritative source for type errors. That way you get fast incremental feedback from PhpStorm and a complete analysis from PHPStan.

8. Comparison: External Tools vs. PhpStorm inspections

The question of when to use External Tools and when to rely on PhpStorm's own inspections is not always obvious. The table below shows the key differences and helps with the decision.

Criterion PhpStorm Inspections External Tools (PHPStan/Psalm/PHPCS) Recommendation
Speed Incremental, instant Seconds to minutes IDE for on-type, tools for on-save/on-demand
Depth of analysis Limited to open files Full call graph PHPStan/Psalm for complete type analysis
Framework knowledge Plugin-dependent Stubs and extensions External tools for Magento-specific patterns
Automatic fixing Quick fixes in the IDE PHPCBF, Psalter Use both, IDE for type fixes, PHPCBF for style
CI parity No CI equivalent Identical to the CI run External tools guarantee CI parity

The decisive advantage of external tools: they run locally with the same configuration files as in the CI pipeline. What is green locally is also green in the pipeline, as long as you work with the same Composer versions and the same PHP version. That is why Docker-based setups such as Mark Shust are so valuable for local quality checks: the environment is identical.

9. Summary

Integrating PHPStan, Psalm and PHP_CodeSniffer into PhpStorm is not a matter of days but of hours, and it pays off every single day. PhpStorm offers External Tools, Run Configurations, File Watchers and native PHPCS integration for exactly this purpose. A sensible combination: PHPCS via File Watcher on save, PHPStan as an External Tool with a shortcut on the current file, Psalm in CI and at the pre-commit hook. PhpStorm's own inspections deliver fast incremental feedback and complement the external tools.

For Magento projects with a Docker setup, it is worth using the wrapper scripts (bin/phpcs, bin/phpstan) in Run Configurations and External Tools, to make sure all tools run inside the container with the correct PHP version and the correct environment variables. A phpstan.neon baseline for existing errors lets you set PHPStan to level 8 without having to fix every legacy issue immediately, while new errors are still caught right away.

PHPStan, Psalm and PHPCS in PhpStorm, the essentials at a glance

PHPStan Setup

External Tool in PhpStorm, $FilePath$ macro for the current file, phpstan.neon at level 8 with a baseline for legacy code. Shortcut for a fast run.

PHPCS Integration

Native integration under Settings → PHP → Quality Tools. PHPCBF as an External Tool with auto-sync. File Watcher for automatic correction on save.

Psalm Use

Stronger on nullability and template types. As an External Tool or in CI/pre-commit. Emacs output format for clickable errors in PhpStorm.

Docker Setup

Use wrapper scripts (bin/phpstan, bin/phpcs) in Run Configurations, guarantees CI parity with an identical PHP version and environment.

Mironsoft

PHP quality assurance, static analysis and code review

Quality assurance in every commit, not only in CI?

We set up PHPStan, Psalm and PHPCS in your PhpStorm workflow, with project-specific rulesets, sensible baselines, and complete Docker integration that runs identically in the pipeline.

Setup & Configuration

Configure PHPStan, Psalm and PHPCS for your project, with baselines and rulesets tailored to your stack

PhpStorm Integration

Set up and document External Tools, File Watchers and Run Configurations for your team

CI Pipeline

Integrate PHPStan and PHPCS into GitHub Actions or GitLab CI, with caching and fail-on-error

10. FAQ: PHPStan, Psalm and PHPCS in PhpStorm

1How do I set up PHPStan as an External Tool in PhpStorm?
Settings → Tools → External Tools → New Tool. Program: PHP/Docker wrapper. Arguments: vendor/bin/phpstan analyse --no-progress $FilePath$. Assign a shortcut in Keymap.
2PHPStan vs. PhpStorm inspections: what is the difference?
Inspections: incremental, instant, current file only. PHPStan: full call graph, framework stubs, project-wide. Combine both sensibly.
3Integrate PHPCS natively into PhpStorm?
Settings → PHP → Quality Tools → PHP_CodeSniffer. Enter the path to the binary, choose the ruleset. PhpStorm then shows PHPCS warnings directly as inspections.
4Set up a File Watcher for PHPCBF?
Settings → Tools → File Watchers. File type PHP, arguments: vendor/bin/phpcbf $FilePath$. Limit the scope to app/code. Enable sync after execution.
5Psalm or PHPStan, which to choose?
PHPStan: more Magento extensions, faster. Psalm: stronger on nullability and template types. Often sensible: PHPStan locally, Psalm in CI.
6What is a PHPStan baseline?
A file with known, accepted errors. Created with --generate-baseline. New errors are caught immediately, legacy issues do not block anything. Ideal for existing projects.
7Ensure CI parity?
Same Composer versions, same PHP version, same configuration files. With a Docker setup and wrapper scripts, the local environment runs exactly as it does in CI.
8Clickable Psalm errors in PhpStorm?
Start Psalm with --output-format=emacs. Output filter regex: $FILE_PATH$:$LINE$:$COLUMN$: $MESSAGE$ entered in the External Tool.
9Why avoid a File Watcher for PHPStan?
PHPStan takes seconds to minutes on larger projects. An on-save trigger interrupts the workflow. Better: shortcut or Run Configuration on demand.
10Integrate the Magento PHPCS ruleset?
composer require --dev magento/magento-coding-standard. Reference the ruleset "Magento2" in phpcs.xml. PhpStorm reads the file automatically from the project root.