PHPCS parses code under a toolchain PHP version, while the plugin still needs runtime tests across its supported PHP range. A careless matrix can duplicate static analysis, reuse incompatible caches, or allow Composer to resolve different standards packages on each runner.
Use this for public plugins, commercial extensions, agency codebases, and WordPress platforms that support several PHP versions and enforce WPCS in GitHub Actions or another CI system.
Quick answer
Run one pinned WPCS job on a documented modern PHP version, run unit and integration tests across the supported runtime matrix, and use PHPCompatibility with an explicit testVersion. Key caches by OS, PHP, and lock-file hash, then keep required checks stable by name.
What to check first
- Document the minimum and maximum PHP versions supported by production, WordPress, dependencies, tests, and code-quality tools.
- Pin Composer dependencies and choose one PHP version that satisfies the complete WPCS toolchain.
- Set PHPCompatibility testVersion independently from the interpreter used to run PHPCS.
- Separate fast syntax, standards, unit, integration, and end-to-end jobs with clear required-check ownership.
- Key Composer and PHPCS caches by lock-file hash and relevant runtime inputs, then test cache misses deliberately.
Diagnostic table
Use this table to keep the work practical. It connects the symptom to evidence and a verification step.
| Action | Evidence to collect | How to verify |
| Define the actual support ranges | Document the minimum and maximum PHP versions supported by production, WordPress, dependencies, tests, and code-quality tools. | The standards report is identical on repeated runs of the same commit. |
| Pin one standards toolchain | Pin Composer dependencies and choose one PHP version that satisfies the complete WPCS toolchain. | Every supported PHP version runs the intended runtime tests. |
| Separate compatibility from runtime | Set PHPCompatibility testVersion independently from the interpreter used to run PHPCS. | PHPCompatibility reports against the documented production range. |
| Design stable required checks | Separate fast syntax, standards, unit, integration, and end-to-end jobs with clear required-check ownership. | Branch protection requires stable checks that still exist after matrix edits. |
Why this usually happens
- Static analysis runtime and application support range are different concerns.
- Composer can select different transitive versions on separate PHP runners.
- A shared cache can restore packages built for another interpreter.
- Branch protection can point to a matrix check name that changes when the matrix changes.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
jobs:
standards:
php: '8.3'
command: vendor/bin/phpcs
tests:
php: ['7.4', '8.1', '8.2', '8.3', '8.4']
compatibility:
php: '8.3'
testVersion: '7.4-'
cache_key: composer-${{ hashFiles('composer.lock') }}
Safe fix order
Do the work in a sequence that makes each result easy to prove. Stop if a step produces new evidence that changes the incident scope.
- Define the actual support ranges
- Pin one standards toolchain
- Separate compatibility from runtime
- Design stable required checks
- Test cache and dependency determinism
Decision rule
Pass when standards findings are deterministic, runtime behavior is tested on every supported PHP line, compatibility rules use the intended range, and caches cannot mix incompatible dependencies.
What to tell the client or owner
Give the owner the affected versions, exact workflow, observed result, business impact, evidence location, temporary control, named owner, and next review time. Remove credentials and personal data from shared screenshots and logs.
Production verification checklist
- The standards report is identical on repeated runs of the same commit.
- Every supported PHP version runs the intended runtime tests.
- PHPCompatibility reports against the documented production range.
- Branch protection requires stable checks that still exist after matrix edits.
Mistakes to avoid
- Do not change several plugins, cache rules, or infrastructure settings before preserving a baseline.
- Do not treat one successful test as proof for retries, alternate clients, background work, or mixed-version fleets.
- Do not paste secrets, personal data, complete production payloads, or customer files into tickets or screenshots.
- Do not close the test until the final user-visible state and the server-side evidence agree.
Questions teams ask during testing
Should WPCS run on the oldest supported PHP version?
Only if the current toolchain supports it. It is usually cleaner to run analysis on a supported modern interpreter and test application runtime separately.
Do we still need syntax lint on every PHP version?
Use the matrix needed to catch real parse differences. Keep it separate from WPCS so failures identify the correct layer.
When HandL WP should help
Bring in HandL WP when a production checkout, form, email, media pipeline, code-quality gate, or paid lead workflow is at risk. We can preserve evidence, isolate the failing layer, make the smallest corrective change, and verify the result across WordPress, connected services, logs, and the user journey.
If this is active on a production site, design a reliable WordPress CI matrix.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Compare Ox Alpha coding scores on equal terms
The Ox Alpha benchmark comparison records numerator, denominator, task family, harness, tools, attempts, token budget, strict pass definition, and limitations before treating a public score as coding evidence.
Related fixes to check next
WP-CLI and WordPress Show Different PHP Versions: Diagnose It: A terminal version check does not tell you which PHP process serves the website. Build a small runtime inventory before changing hosting settings.
Helpful references