code quality and tooling

Local Quality Gates for PHP Examples

A local quality gate is a set of checks you run before asking other people or CI to review your code. In PHP projects, this usually includes syntax checks, formatting checks, static analysis, and tests.

The purpose is not to make development slower. The purpose is to catch obvious problems locally while they are cheap to fix.

What a quality gate checks

A practical PHP quality gate might include:

  • php -l to catch syntax errors
  • PHP-CS-Fixer or PHP_CodeSniffer to check style
  • PHPStan or Psalm to check types and structure
  • PHPUnit to check behaviour
  • Rector dry-run when the project uses automated refactoring

Not every project uses every tool. Follow the repository.

Composer scripts make checks repeatable

Instead of asking every developer to remember long commands, put them in composer.json.

{
  "scripts": {
    "lint": "find src tests -name '*.php' -print0 | xargs -0 -n1 php -l",
    "format:check": "php-cs-fixer fix --dry-run --diff",
    "analyse": "phpstan analyse",
    "test": "phpunit",
    "check": [
      "@lint",
      "@format:check",
      "@analyse",
      "@test"
    ]
  }
}

Then the local command is simple:

composer check

Use the scripts already present in the project. If the project has no scripts, adding them can be a useful improvement.

Syntax checks are fast

php -l checks whether a file has valid PHP syntax. It does not run the program.

php -l src/OrderTotal.php

Syntax checks catch missing braces, invalid tokens, and parse errors. They do not prove business logic.

Formatting checks prevent noisy reviews

Run the formatter in check mode before a pull request.

vendor/bin/php-cs-fixer fix --dry-run --diff

or:

vendor/bin/phpcs

The exact command depends on the formatter.

Static analysis catches type problems

Run the project's static analyser.

vendor/bin/phpstan analyse

or:

vendor/bin/psalm

Static analysis is especially useful for catching wrong return types, missing array keys, nullable values used unsafely, and incorrect PHPDoc.

Tests prove behaviour

Tests answer a different question from formatting and static analysis. They check that the code behaves as expected.

vendor/bin/phpunit

For a small bug fix, a focused test around the changed rule is often better than only clicking around manually.

Run checks before pushing

A useful workflow:

git status --short
composer check
git diff

Run checks, then review the diff. If a formatter changes files, inspect that diff before committing.

Do not hide failures

If a check fails, read the first failure carefully. Fix the root cause. Avoid weakening the check just to make the command pass.

Bad responses include:

  • ignoring all static analysis errors globally
  • removing a test because it fails
  • committing generated files to satisfy a missing path
  • suppressing a warning without understanding it
  • skipping the formatter because the diff is inconvenient

What to remember

A local quality gate is the developer's first line of defence. It should be easy to run, repeatable, and close to the same checks CI will run.

Before moving on, make sure you can describe what composer check should do in a PHP project and why formatting, static analysis, and tests catch different problems.

Practice

Task: Build A Composer Quality Gate

Create Composer scripts for a small PHP project quality gate.

Requirements

  • Add a format:check script using PHP-CS-Fixer dry-run with diff.
  • Add an analyse script using PHPStan.
  • Add a test script using PHPUnit.
  • Add a check script that runs all three.
  • Explain why check should be run before opening a pull request.
Show solution
{
  "scripts": {
    "format:check": "php-cs-fixer fix --dry-run --diff",
    "analyse": "phpstan analyse",
    "test": "phpunit",
    "check": [
      "@format:check",
      "@analyse",
      "@test"
    ]
  }
}

Run the full local gate with:

composer check

composer check should be run before opening a pull request because it catches formatting, static-analysis, and behaviour failures before reviewers or CI spend time on them.