PHPStan, PHPUnit, PHPCS and Rector before the commit
If you only find out about quality gates in the CI pipeline, you lose minutes or hours on feedback loops that could have been resolved locally in seconds. PHPStan, PHPUnit, PHPCS and Rector can be integrated into PhpStorm so that errors become visible right at the moment you save, without ever leaving the command line.
Table of Contents
- 1. Why quality gates should run locally, not only in CI
- 2. Setting up PHPStan in PhpStorm
- 3. Configuring the PHPUnit integration and test runner
- 4. PHPCS and PHPCBF as an on-save action
- 5. Rector as an external tool for automatic refactoring
- 6. Remote PHP interpreter for Docker setups
- 7. Run configurations: everything with a single click
- 8. Controlling git hooks from within PhpStorm
- 9. Quality gate strategies compared
- 10. Summary
- 11. FAQ
1. Why quality gates should run locally, not only in CI
The classic approach: write code, push, wait for the result in CI. If PHPStan level 8 finds three spots that are not correct, you fire up the IDE again, find the line, fix it, push again, wait. On a medium-sized PHP project, this cycle easily costs 10 to 20 minutes per round. Multiplied by several commits per day and several developers, that turns into a measurable loss of productivity that can be avoided entirely.
With its external tools, run configurations and native PHPUnit integration, PhpStorm provides all the building blocks needed to pull PHPStan, PHPUnit, PHPCS and Rector directly into the IDE. The result: PHPStan errors show up as a red underline directly in the editor, PHPCS violations are fixed on save, and a Rector run is a single keystroke away. CI then serves only as a final safety net, no longer as the primary feedback tool.
For Magento 2 projects that use PHP 8.4 with strict types, this is particularly relevant. Magento ships many classes with complex types, and PHPStan at level 6 or higher quickly finds real bugs there, but only if the right extensions are loaded. In PhpStorm you can store this configuration once and then be sure, on every single run, that exactly the same analysis executes as in CI.
2. Setting up PHPStan in PhpStorm
PhpStorm has no native PHPStan integration through a dedicated UI panel, but external tools are the right approach. Under Settings → Tools → External Tools you create a new tool: the program is the path to the PHPStan binary (for a Composer install, $ProjectFileDir$/vendor/bin/phpstan), and the arguments are analyse --configuration=$ProjectFileDir$/phpstan.neon --error-format=checkstyle $FilePath$. As the working directory you set $ProjectFileDir$. With the checkstyle format, PhpStorm can parse the output directly and display errors as annotations in the editor, once you link the output with the corresponding file filter.
The more elegant solution is a quality tools plugin (for example the official PHPStan plugin from the Marketplace). It reads the phpstan.neon from the project, knows the configured level, and shows errors as you type, without a manual invocation. For Docker-based projects, the PHP interpreter needs to point to the remote interpreter (more on that in section 6), so that PHPStan works against the project configuration inside the container instead of a potentially different local PHP.
# phpstan.neon - configuration for Magento 2 with PHP 8.4
parameters:
level: 6
paths:
- app/code/Mironsoft
excludePaths:
- app/code/Mironsoft/*/Test
# Magento-specific PHPStan extension
bootstrapFiles:
- vendor/magento/magento2-base/dev/tests/static/bootstrap.php
ignoreErrors:
# Magento magic methods, known false positives
- '#Call to an undefined method Magento\\Framework\\#'
checkMissingIterableValueType: false
reportUnmatchedIgnoredErrors: false
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neon
- vendor/bitexpert/phpstan-magento/extension.neon
For everyday use, a two-tier strategy is recommended: a "Fast" profile analyzes only the currently open file ($FilePath$), a "Full" profile analyzes the entire module. Both can be set up as separate external tools and made reachable via keyboard shortcuts. That way the fast feedback loop for the current work stays intact, while a full analysis is available at the press of a button.
3. Configuring the PHPUnit integration and test runner
The PHPUnit integration in PhpStorm is one of the most mature of all native integrations. Under Settings → PHP → Test Frameworks you create a PHPUnit configuration. For Composer-based projects you choose "PHPUnit by Composer autoloader" and provide the path to vendor/autoload.php. The configuration file (phpunit.xml or phpunit.xml.dist) is detected automatically once it sits in the project root. PhpStorm reads the test suites from it and makes them available in the test runner panel.
Once configured, you can start individual tests by clicking the green play icon next to the method, run an entire test suite in the run panel, or use the coverage runner to display code coverage with inline highlighting. For Magento 2 unit tests you need to make sure the autoloader points correctly to the Magento bootstrap and that all necessary bootstrap files are included, because Magento ships its own object factory that PHPUnit does not know about without a bootstrap.
<?xml version="1.0" encoding="UTF-8"?>
<!-- phpunit.xml - Magento 2 unit tests with PhpStorm compatibility -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="dev/tests/unit/framework/bootstrap.php"
colors="true"
columns="120"
stopOnFailure="false">
<testsuites>
<testsuite name="Mironsoft Unit Tests">
<directory>app/code/Mironsoft/*/Test/Unit</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">app/code/Mironsoft</directory>
</include>
<exclude>
<directory>app/code/Mironsoft/*/Test</directory>
</exclude>
</coverage>
<php>
<const name="TESTS_CLEANUP" value="disabled"/>
<const name="MAGENTO_EXTRA_VERBOSE_CONFIG_ARRAY" value="1"/>
</php>
</phpunit>
4. PHPCS and PHPCBF as an on-save action
PHPCS can be set up in PhpStorm as a native code quality tool: Settings → PHP → Quality Tools → PHP Code Sniffer. There you provide the path to the binary and the ruleset. With "Show warnings as" set to "Error" or "Warning", violations show up directly in the editor as colored markers, without a manual invocation. It is important that the ruleset uses the same standard as CI, otherwise developers fix something locally that CI reports as an error again.
PHPCBF is the automatic counterpart: it fixes every automatically fixable PHPCS violation. Set up as an external tool in PhpStorm, you can apply PHPCBF to the current file with a shortcut. Even more convenient is the integration as a file watcher or as an action under Settings → Tools → Actions on Save. Since PhpStorm 2023 there are dedicated entries there for external tools, so PHPCBF runs automatically after every save, the cursor does not jump, and the file is silently corrected.
5. Rector as an external tool for automatic refactoring
Rector is not a linter, it is an automatic code transformer: it reads PHP code, applies configured rules, and writes the file back. In a CI pipeline, Rector runs in "dry-run" mode and reports what it would change. Locally in PhpStorm you want to run Rector directly, so the transformations become visible immediately. Set up as an external tool: program vendor/bin/rector, arguments process $FilePath$ --config=rector.php, working directory $ProjectFileDir$.
After execution, PhpStorm automatically opens the diff view if you have "Open console" enabled and Rector made changes. Alternatively, the integration works through the git diff panel: Rector changes the file on disk, PhpStorm detects the change, and displays it in the diff. For PHP 8.4 upgrades, constructor property promotion, typed class constants, readonly properties, the corresponding Rector sets are enabled with a few lines in rector.php.
<?php
// rector.php - configuration for PHP 8.4 upgrade and Magento 2
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector;
return RectorConfig::configure()
->withPaths([
__DIR__ . '/app/code/Mironsoft',
])
->withSkip([
__DIR__ . '/app/code/Mironsoft/*/Test',
])
->withSets([
LevelSetList::UP_TO_PHP_84,
SetList::TYPE_DECLARATION,
SetList::EARLY_RETURN,
])
->withRules([
AddReturnTypeDeclarationRector::class,
TypedPropertyFromAssignsRector::class,
])
// do not touch Magento generated classes
->withSkip([
'*/generated/*',
'*/setup/src/*',
]);
6. Remote PHP interpreter for Docker setups
For Docker-based development environments like the Mark Shust setup, there are two approaches for quality tools in PhpStorm: use a local PHP interpreter (which may have different extensions) or use the interpreter directly inside the container. The second path is the correct one. Under Settings → PHP you add a new interpreter, choose "From Docker, Vagrant, VM, WSL, Remote" and configure the Docker connection. PhpStorm then connects to the running container and uses its PHP binary and all installed extensions.
This means PHPStan runs with exactly the same PHP version, the same extensions and the same configuration as in CI. PHPCS finds the same dependencies. PHPUnit uses the same autoloader. Parity between local analysis and CI analysis is thereby guaranteed, a common problem in teams where one developer has PHP 8.3 locally but CI runs PHP 8.4 is completely eliminated.
7. Run configurations: everything with a single click
Run configurations in PhpStorm are named, reusable execution plans. You create them under Run → Edit Configurations. For quality gates, compound configurations are a good fit: a single configuration starts PHPStan, then PHPUnit, then PHPCS in sequence and shows all results in their own tab. That way a single click or shortcut is enough to check every quality gate, ideal before a commit or a merge request.
Run configurations can also be checked into the repository as a file (.run/). That means every team member gets the same preconfigured quality gate runs the first time they open the project. New developers do not have to set up anything manually: the PHP interpreter is defined through the Docker configuration, the binaries live in the vendor directory, and the run configuration points to the right paths. Onboarding for the quality gate setup then takes minutes instead of hours.
8. Controlling git hooks from within PhpStorm
Under Settings → Version Control → Git → Commit, PhpStorm offers the option to run actions before the commit: "Run Tests" starts the PHPUnit suite, "Analyze code" runs the configured inspections. This is the IDE-side equivalent of a pre-commit hook. The advantage over a shell hook: you see the result immediately in the commit dialog, can jump straight to the affected spot on error, and can abort the commit or proceed anyway.
For teams that use both PhpStorm and other editors, a combination is recommended: PhpStorm-side pre-commit checks as a convenient interface, plus a bash-based pre-commit hook as a safety net. The hook calls the same binaries (vendor/bin/phpstan analyse, vendor/bin/phpcs), so quality gates still apply even if someone commits from the command line. The configuration in both cases is the same phpstan.neon and .phpcs.xml.
9. Quality gate strategies compared
There are several strategies for enforcing quality gates in a PHP project. The choice depends on team size, CI setup and IDE preferences. The table below shows the main approaches and their trade-offs.
| Strategy | Feedback time | Setup effort | Recommendation |
|---|---|---|---|
| CI pipeline only | 5 to 15 min | Low | Only as a fallback, not as the primary gate |
| Pre-commit hook | 30 to 120 sec | Medium | Solid safety net, no IDE feedback |
| PhpStorm external tools | 2 to 10 sec | Medium | Fast, but manual invocation |
| PhpStorm on-save + plugin | Instant | Higher | Best UX, recommended for active development |
| All layers combined | Instant plus safety net | Highest | Ideal for teams with a mandatory CI gate |
The combination of PhpStorm on-save actions for PHPCS/PHPCBF, the PHPStan plugin for real-time analysis, and compound run configurations for the full gate run before a commit is the practically optimal approach. CI remains as the final safety net, but the vast majority of errors never even get committed in the first place.
Mironsoft
PHP code quality, Magento 2 development and DevOps integration
Quality gates that apply before the commit?
We set up PHPStan, PHPUnit, PHPCS and Rector in PhpStorm, with a remote interpreter for Docker, compound run configurations and CI parity, so errors are visible before you push.
PHPStan setup
Level 6+ with the Magento extension, remote interpreter and PhpStorm plugin integration
Rector automation
PHP 8.4 upgrades and code transformations as a one-click action in PhpStorm
CI parity
Keep local and CI configuration in sync, no more "works on my machine"
10. Summary
Bundling PHPStan, PHPUnit, PHPCS and Rector in PhpStorm means shrinking the feedback cycle from minutes to seconds. PHPStan, as a plugin or external tool, shows type errors right in the editor. PHPCS flags style deviations, PHPCBF fixes them automatically on save. PHPUnit runs with a single click as a run configuration, with coverage highlighting directly in the file. Rector transforms code at the press of a button, and the result is immediately visible in the diff.
The key is CI parity: the same phpstan.neon, the same phpunit.xml, the same PHPCS ruleset locally and in the pipeline. With a remote PHP interpreter for Docker-based setups, it is guaranteed that local analysis and CI analysis run on identical prerequisites. That eliminates the most common source of "works locally, fails in CI": differing PHP versions, missing extensions, and diverging configurations.
Quality gates locally in PhpStorm, the essentials at a glance
PHPStan & PHPCS
Plugin or external tool, errors show up in the editor immediately. PHPCS via an on-save action: violations are fixed automatically before they get committed.
PHPUnit integration
Native test runner in PhpStorm, individual tests via icon, coverage with inline highlighting. Configure it once, available to every team member.
Rector as a refactoring tool
External tool for automatic code transformations. PHP 8.4 upgrades with a single keystroke. Result visible immediately in the git diff.
Remote interpreter & CI parity
Use the Docker interpreter in PhpStorm, identical PHP version and extensions as CI. Compound run configurations for a full gate run before the commit.