Master PHP Code Quality: PHPStan, Rector, Pint & PHP CS Fixer
Learn to enforce PHP code quality with PHPStan, Rector, Pint, and PHP CS Fixer.
20+ years shipping production PHP systems at scale. Everything here is grounded in real deployments.
- ✓Basic knowledge of PHP syntax and OOP.
- ✓Composer installed for dependency management.
- ✓A PHP project (version 7.4 or higher recommended).
- PHPStan Static analysis to find bugs without running code.
- Rector Automated refactoring and upgrades (e.g., PHP 7.4 to 8.0).
- Pint Laravel's opinionated PHP CS Fixer wrapper.
- PHP CS Fixer Enforces PSR-12 and custom coding standards.
Think of these tools like a team of code inspectors: PHPStan is a detective finding hidden bugs, Rector is a renovation crew updating old code, and Pint/CS Fixer are style enforcers ensuring everyone writes neatly.
In the rush to ship features, code quality often takes a backseat. But technical debt, inconsistent styles, and subtle bugs can slow down your team and lead to production outages. PHP developers now have a powerful arsenal of tools to automate quality checks: PHPStan for static analysis, Rector for automated refactoring, and Pint/CS Fixer for coding standards. This tutorial will guide you through setting up and integrating these tools into your workflow, with real-world examples and debugging strategies. By the end, you'll have a production-ready pipeline that catches errors before they reach users, modernizes legacy code, and enforces a consistent style across your team.
1. Setting Up PHPStan for Static Analysis
PHPStan is a static analysis tool that finds bugs in your code without running it. It understands PHP's type system and can detect issues like calling methods on null, accessing undefined properties, and more. To get started, install it via Composer: composer require --dev phpstan/phpstan. Then create a phpstan.neon configuration file in your project root. Here's a basic setup:
``neon parameters: level: 6 paths: - src ``
Level 6 is a good starting point for most projects. Run PHPStan with vendor/bin/phpstan analyse. You'll likely see errors – that's normal! Use the baseline feature to ignore existing errors and focus on new ones: vendor/bin/phpstan analyse --generate-baseline. This creates a phpstan-baseline.neon file. Over time, fix the baseline errors and increase the level.
--memory-limit to avoid OOM on large codebases.2. Automating Refactoring with Rector
Rector is a tool that performs automated refactoring of PHP code. It can upgrade your codebase to newer PHP versions, apply coding standards, and even rename methods. Install it via composer require --dev rector/rector. Create a rector.php config file:
```php <?php
use Rector\Config\RectorConfig; use Rector\Set\ValueObject\SetList;
return RectorConfig::configure() ->withPaths([__DIR__ . '/src']) ->withSets([ SetList::PHP_80, SetList::CODE_QUALITY, ]); ```
Run Rector with vendor/bin/rector process src/ --dry-run to see proposed changes. Remove --dry-run to apply them. Rector is powerful but can be aggressive; always review changes in version control.
3. Enforcing Coding Standards with PHP CS Fixer
PHP CS Fixer is a tool that automatically fixes PHP coding standards issues. It supports PSR-12 and many other rules. Install it: composer require --dev friendsofphp/php-cs-fixer. Create a .php-cs-fixer.dist.php config:
```php <?php
$finder = PhpCsFixer\Finder::create() ->in(__DIR__ . '/src') ->exclude('vendor');
return (new PhpCsFixer\Config()) ->setRules([ '@PSR12' => true, 'array_syntax' => ['syntax' => 'short'], 'ordered_imports' => true, ]) ->setFinder($finder); ```
Run with vendor/bin/php-cs-fixer fix. Use --dry-run to preview changes. Integrate into your IDE or pre-commit hook.
--diff to see changes in pull requests.4. Laravel Pint: A Simpler Alternative
Laravel Pint is an opinionated PHP CS Fixer wrapper built for Laravel projects. It comes pre-configured with Laravel's coding style. Install it: composer require --dev laravel/pint. Run with ./vendor/bin/pint. Pint requires no configuration by default, but you can customize it via a pint.json file:
``json { "preset": "laravel", "rules": { "simplified_null_return": true } } ``
Pint is faster than PHP CS Fixer because it uses a subset of rules. It's ideal for Laravel developers who want a zero-config solution.
--test to check if files are correctly formatted.5. Integrating Tools into CI/CD Pipeline
To ensure code quality consistently, integrate these tools into your CI/CD pipeline (e.g., GitHub Actions). Here's a sample workflow that runs PHPStan, Rector (dry-run), and Pint (test) on every push:
```yaml name: Code Quality
on: [push]
jobs: quality: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: '8.2' - run: composer install - run: vendor/bin/phpstan analyse --level=6 --no-progress - run: vendor/bin/rector process src/ --dry-run --no-progress - run: vendor/bin/pint --test ```
This pipeline will fail if any tool finds issues, preventing bad code from being merged.
6. Advanced Configuration and Custom Rules
All four tools support advanced customization. For PHPStan, you can create custom rules by implementing PHPStan\Rules\Rule. For Rector, you can write custom rectors. For PHP CS Fixer, you can define custom fixers. Here's an example of a custom PHPStan rule that disallows var_dump:
```php <?php
use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule;
/* @implements Rule<Node\Expr\FuncCall> */ class NoVarDumpRule implements Rule { public function getNodeType(): string { return Node\Expr\FuncCall::class; }
public function processNode(Node $node, Scope $scope): array { if ($node->name instanceof Node\Name && $node->name->toString() === 'var_dump') { return ['Use of var_dump is not allowed. Remove it.']; } return []; } } ```
Register it in phpstan.neon:
``neon services: - class: NoVarDumpRule tags: - phpstan.rules.rule ``
This gives you fine-grained control over your codebase.
The Null Coalescing Nightmare: How PHPStan Saved a Deployment
- Always use static analysis to catch type errors before deployment.
- Don't assume variables are set; use nullable types and null checks.
- Integrate PHPStan into CI to block merging with errors.
- Educate team on PHP 8.0+ type strictness.
- Use PHPStan's bleeding edge rules for maximum safety.
@property PHPDoc for magic properties.--dry-run first. Review the diff before applying.--diff to see changes.vendor/bin/phpstan analyse --level=5vendor/bin/phpstan analyse --generate-baseline@phpstan-ignore-next-line comments sparingly.| File | Command / Code | Purpose |
|---|---|---|
| phpstan.neon | parameters: | 1. Setting Up PHPStan for Static Analysis |
| rector.php | use Rector\Config\RectorConfig; | 2. Automating Refactoring with Rector |
| .php-cs-fixer.dist.php | $finder = PhpCsFixer\Finder::create() | 3. Enforcing Coding Standards with PHP CS Fixer |
| pint.json | { | 4. Laravel Pint |
| .github | name: Code Quality | 5. Integrating Tools into CI/CD Pipeline |
| NoVarDumpRule.php | use PhpParser\Node; | 6. Advanced Configuration and Custom Rules |
Key takeaways
Common mistakes to avoid
4 patternsRunning Rector without dry-run first
Ignoring PHPStan errors by setting level to 0
Using Pint with a custom config that conflicts with Laravel preset
Not caching PHPStan results
Interview Questions on This Topic
What is static analysis and how does PHPStan help?
Frequently Asked Questions
20+ years shipping production PHP systems at scale. Everything here is grounded in real deployments.
That's Advanced PHP. Mark it forged?
3 min read · try the examples if you haven't