Phase 5 · Professional ApplicationsModule 32~48 min read

Static Analysis, Style & Refactoring

Use standards, formatters, static analysis, automated upgrades, and quality gates to improve code safely.

What you'll learn

Let tools find entire classes of mistakes before runtime. PSR-12 formatting removes style debate, static analysis checks data flow, and small behavior-protected refactors improve structure without changing results.

By the end of this lesson, you'll be able to:

  • Configure a consistent style check
  • Add precise types for static analysis
  • Refactor in small test-protected steps

Core mental model

Professional PHP is less about memorizing APIs and more about choosing a clear boundary for each responsibility. Use this table as a decision guide while reading the examples.

ConceptWhat it protectsDecision rule
Static analysisImpossible-path detectionRaise strictness gradually and keep the baseline shrinking.
FormatterMechanical consistencyAutomate style instead of reviewing it manually.
RefactorStructural improvementPreserve externally observable behavior.

Professional workflow

Build the feature in small, verifiable steps. Each step leaves the system in a state you can test.

  1. Describe the quality gate boundary: its inputs, outputs, invariants, and expected failures.
  2. Implement the smallest happy path behind an explicit contract.
  3. Add validation and translate low-level failures into language the caller understands.
  4. Exercise the boundary with realistic data, then inspect output, logs, and resource cleanup.
  5. Refactor only after behavior is protected by a repeatable check.

Make the boundary visible

Name inputs, outputs, side effects, and failure cases before adding framework or infrastructure code. That habit keeps advanced PHP understandable as the application grows.

Guided code lab

Teach the analyzer collection shapes

Generics in PHPDoc let tools prove each item supports the operations used in the loop.

CourseCatalog.php
<?php
final class CourseCatalog
{
    /** @param list<Course> $courses @return list<string> */
    public function publishedTitles(array $courses): array
    {
        return array_values(array_map(
            static fn (Course $course): string => $course->title(),
            array_filter($courses, static fn (Course $course): bool => $course->isPublished()),
        ));
    }
}

Run one local quality command

The pipeline is explicit, reproducible, and fails before unverified code is merged.

composer.json
{
  "scripts": {
    "format:check": "php-cs-fixer fix --dry-run --diff",
    "analyse": "phpstan analyse src tests --level=max",
    "test": "phpunit",
    "check": ["@format:check", "@analyse", "@test"]
  }
}

Production practice

Contract

Quality configuration belongs in version control and the same command runs locally and in CI.

Verification

Protect behavior with tests before refactoring; make one transformation, then run the smallest relevant check.

Operations

Pin tool versions, cache safely in CI, and review automated upgrade diffs like any other code.

Common failure mode

A permanent baseline can become a landfill for new errors. Baseline only legacy debt, reject growth, and remove entries as code changes.

Independent workshop

Take an untyped legacy service to maximum practical analysis strictness while preserving its public API.

Your finished workshop must include:

  • Characterization tests
  • Typed DTOs and collection shapes
  • Green style, analysis, and test command with no new baseline

Definition of done

Run the happy path and at least two failure paths, explain one design tradeoff in a short README, and leave the code formatted and ready for review.

Recap & quick check

Key takeaways

  • Automation makes quality repeatable.
  • Precise types improve both tools and design.
  • Refactoring changes structure, not behavior.
  • Quality gates stop regressions before merge.

Quick check

1. What does a refactor intentionally preserve?

2. Why format automatically?

3. What should happen to a static-analysis baseline?

Keep the workshop: later phases deliberately build on these boundaries, so today's small example can become part of your portfolio architecture.