- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
Laravel Pint, PHPStan and Rector: Automatic Code Quality Without the Arguments
About Post
Code review time is precious, and too much of it goes on things a machine could have caught. "Missing space here." "Unused import." "This can be null." "We stopped writing it this way two versions ago."
None of those comments are wrong. They're just a waste of a human. A reviewer's attention should go to the questions only a person can answer: is this the right design, does it handle the edge cases, will we understand it in a year?
Three tools take the rest off your plate in a Laravel project: Pint formats, PHPStan (with Larastan) finds bugs without running the code, and Rector rewrites code automatically. Here's how to set them up, in the order I'd introduce them to an existing project, and how to make CI enforce them.
Three tools, three different jobs
| Tool | Question it answers | Changes your code? |
|---|---|---|
| Pint | Does it look consistent? | Yes, formatting only |
| PHPStan + Larastan | Could this break at runtime? | No, it only reports |
| Rector | Could this be written in a newer or simpler way? | Yes, real refactors |
Step 1: Pint, and the end of formatting debates
Pint is Laravel's code style fixer, built on PHP-CS-Fixer, and new Laravel apps already include it as a dev dependency. With no config at all, it applies the Laravel preset:
./vendor/bin/pint # fix everything
./vendor/bin/pint --test # only report, exit with an error if anything is off (for CI)
./vendor/bin/pint --dirty # only files with uncommitted changes
If you want to adjust the style, add a pint.json to the project root with a preset and any rule overrides. But I'd resist the urge to customise much. The value of Pint isn't that its style is perfect; it's that nobody ever argues about style again.
One tip for an existing project: run Pint across everything in a single, separate commit with no other changes, then add that commit's hash to a .git-blame-ignore-revs file. GitHub's blame view honours that file, and locally you can point git config blame.ignoreRevsFile at it, so git blame skips the formatting commit and still shows who actually wrote each line.
Step 2: PHPStan with Larastan, finding bugs before users do
PHPStan reads your code and reports things that would fail at runtime: calling a method on something that might be null, passing the wrong type, using a property that doesn't exist. Plain PHPStan doesn't understand Laravel's magic (facades, Eloquent attributes, relationships), so install Larastan, which teaches it:
composer require --dev larastan/larastan
# phpstan.neon
includes:
- vendor/larastan/larastan/extension.neon
parameters:
paths:
- app/
level: 5
Then run ./vendor/bin/phpstan analyse. Once you reach level 8, where PHPStan starts checking nullable types, you'll see classics like this:
$contract = Contract::find($id);
return $contract->tenant->name;
// Cannot access property $tenant on App\Models\Contract|null.
Fair point. find() returns null for a missing ID. That's a 500 error waiting for the first bad link, and PHPStan spotted it without running a single request. (Here, findOrFail() is the honest fix.)
Levels and the baseline trick
PHPStan has rule levels, from 0 (basic checks) up to max (very strict, including how carefully you handle mixed types). On an older project, a high level can produce hundreds of errors on day one, which is how tools get uninstalled.
The fix is the baseline. Run ./vendor/bin/phpstan analyse --generate-baseline and PHPStan writes every current error into phpstan-baseline.neon. Include that file in your config, and from now on only new errors fail the build. Existing debt is frozen, and you can chip away at it whenever you touch a file. Raise the level one step at a time once the baseline shrinks.
Step 3: Rector, the refactoring robot
Rector goes further than reporting. It applies rules that rewrite code: adding type declarations, removing dead code, converting old syntax to newer PHP features, and helping with framework upgrades.
// rector.php
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withPaths([__DIR__ . '/app', __DIR__ . '/tests'])
->withPhpSets() // reads your PHP version from composer.json
->withPreparedSets(deadCode: true, codeQuality: true);
Always start with a dry run, which prints a diff of what it would change:
./vendor/bin/rector process --dry-run
For Laravel-specific rules, there's a community package, driftingly/rector-laravel, with sets for things like moving to newer Laravel conventions. Treat its output like any refactor: review it, run the tests, merge in small batches.
A word of caution: Rector is a power tool. Enable a few rule sets, review the diffs, commit, then add more. Turning on everything at once produces a diff nobody can review, and an unreviewable diff is just a gamble.
The order matters: run Rector first (it changes code), then Pint (it formats whatever Rector wrote), then PHPStan (it checks the final result). Run them in that order locally and in CI.
Step 4: Make CI the bad cop
Tools that run "when someone remembers" don't run. Put them in a Composer script so everyone uses the same command:
"scripts": {
"quality": [
"rector process --dry-run",
"pint --test",
"phpstan analyse --no-progress"
]
}
Then call composer quality in your pipeline on every pull request, before the tests. A minimal GitHub Actions job:
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
- run: composer install --no-interaction --prefer-dist
- run: composer quality
- run: php artisan test
Now the pipeline makes the boring comments, and it makes them before a reviewer even opens the pull request. Nobody takes it personally when a robot points out a missing type.
Bonus: they make AI-written code better too
If you use Claude Code, Cursor or Copilot, these tools become even more valuable. Tell the agent to run composer quality and the tests before it says it's done. It gets fast, objective feedback, fixes its own type errors and formatting, and you review a cleaner diff. Static analysis is one of the best guardrails you can give an AI agent, because it doesn't care how confident the code looks.
The setup in five lines
- Pint for formatting, applied once in a separate commit, then enforced with
--test. - PHPStan with Larastan at a sensible level, with a baseline for existing code.
- Rector with a few rule sets, always reviewed through
--dry-runfirst. - One Composer script, run in that order.
- CI runs it on every pull request, so humans can review what matters.
Which PHPStan level is your main project on right now, and what's stopping you from going one higher?

Be first to comment it...