01Install the scanner outside the client application.
Use a new, disposable tools directory beside a development copy of the project. This keeps the scanner’s Composer files separate from the application. The example assumes sibling folders upgrade-tools and client-project; replace the project path with your own.
mkdir upgrade-tools
cd upgrade-tools
composer init --name="local/php-upgrade-tools" --no-interaction
composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
composer require --dev "phpcompatibility/php-compatibility:^10.0.0@dev"
php vendor/bin/phpcs -i
Confirm PHPCompatibility appears in the installed standards. The constraint above follows the current upstream development installation instructions; let Composer check the runtime requirements. Retain the generated composer.lock and avoid dependency updates between comparison scans.
Sources: PHPCompatibility installation and Composer lock-file usage.
02Write a baseline for one explicit PHP target.
From the tools directory, this example scans PHP and INC files for PHP 8.4 compatibility. It excludes dependency directories to demonstrate an explicit scope; review those dependencies separately. Choose the target, file types, and exclusions your project actually needs.
php vendor/bin/phpcs --standard=PHPCompatibility --runtime-set testVersion 8.4 --extensions="php,inc" --ignore="*/vendor/*,*/node_modules/*" --report=json --report-file=baseline.json "../client-project"
--report=json selects structured output; --report-file writes it to a file instead of relying on shell redirection. Open the resulting file and confirm it contains a files object. Keep the command and tool versions with the evidence:
php --version
php vendor/bin/phpcs --version
composer show phpcompatibility/php-compatibility
Sources: PHP target selection, PHPCS JSON reporting, and exit-status behavior.
03Make the next scan comparable.
After reviewed code changes in the same project path, repeat the scan with only the output filename changed:
php vendor/bin/phpcs --standard=PHPCompatibility --runtime-set testVersion 8.4 --extensions="php,inc" --ignore="*/vendor/*,*/node_modules/*" --report=json --report-file=current.json "../client-project"
| KEEP CONSISTENT | WHAT TO RECORD |
|---|---|
| Scan coverage | Project path, included directories, extensions, ignored paths, and in-code suppressions. |
| Rules and filtering | Standard, custom ruleset, excluded sniffs, severity thresholds, and warning visibility. |
| Tooling and target | Composer lock file, PHPCS/PHPCompatibility versions, PHP CLI version, and testVersion. |
| Code being assessed | Commit or revision, scan date, and intentional dependency or configuration changes. |
Changing a report’s “Target PHP” label does not rerun PHPCompatibility. To assess a different target, change testVersion in the scan command and generate fresh JSON. If you change the toolchain or coverage, describe the difference; do not present the count change as repair progress.
PHPCS documents file extensions, ignores, sniff selection, and severity filtering in its advanced usage guide.
04Explain the comparison precisely.
In UpgradeBrief, import current.json as the current report and baseline.json as the optional baseline. Matching uses the filename, rule/source, and message; line movement alone does not make a finding new. Duplicate occurrences are counted individually.
Matching evidence is still present. Its severity, type, or line number may have changed.
No matching baseline occurrence was found. Check whether scope or tool changes explain it.
A baseline occurrence is absent from the current import. Absence is not proof of a repair.
Before sending the brief, remove a shared local filename prefix if appropriate—for example /home/alex/client-project/. Apply consistent path handling to both scans. This changes filenames only; diagnostic messages and project notes may still contain private information. Review every export.
05Turn static evidence into an upgrade plan.
For each priority, record the affected behavior, a proposed change, who owns it, and the staging check that will verify it. Keep code and data backups and a tested rollback plan before a production runtime change.
A report with zero errors is not a runtime-readiness certificate. Static analysis has incomplete coverage. Validate real workflows, extensions, dependencies, integrations, logs, and data behavior on the target runtime.
PHPCompatibility describes its coverage limits in PHP version support.