0x55aa
← Back to Blog

Laravel Pint: Stop Arguing About Code Style Forever 🫧

6 min read

Laravel Pint: Stop Arguing About Code Style Forever 🫧

I once watched two senior developers spend 45 minutes in a pull request arguing about whether a closing brace should go on its own line. 45 minutes. We were building an e-commerce checkout at Cubet that was literally losing money every hour it wasn't live. And there we were. Debating braces.

Never again.

Enter Laravel Pint — Laravel's official, opinionated PHP code style fixer. One command. Zero arguments. Beautiful code.

What Even Is Laravel Pint? 🤔

Pint is a zero-configuration PHP code style fixer built on top of PHP-CS-Fixer. Laravel ships it in every new project since Laravel 10. It's like having a really strict (but fair) senior dev who fixes your code style automatically without making it personal.

Think of it as autocorrect for your code. Except it actually works, unlike iOS autocorrect trying to change "public function" to "Public fuNction" for some reason.

The Setup Is Embarrassingly Easy ⚡

If you're on Laravel 10+, Pint is already in your composer.json:

# Just run it
./vendor/bin/pint

That's it. That's the whole setup section. You're welcome.

For older projects:

composer require laravel/pint --dev
./vendor/bin/pint

Before and After: The Glow-Up Is Real ✨

Here's what I saw in a real codebase I inherited at work. A controller method that looked like it was written during a power outage:

Before Pint (someone's actual code, identity protected):

class OrderController extends Controller {
  public function store( Request $request ){
    $order=Order::create(['user_id'=>auth()->id(),'total'=>$request->total,'status'=>'pending']);
    if($order){
      event(new OrderPlaced($order));
    Mail::to($request->user())->send(new OrderConfirmation($order));
    }
    return response()->json(['order'=>$order],201);
  }
}

After Pint (same code, actual human):

class OrderController extends Controller
{
    public function store(Request $request)
    {
        $order = Order::create([
            'user_id' => auth()->id(),
            'total' => $request->total,
            'status' => 'pending',
        ]);

        if ($order) {
            event(new OrderPlaced($order));
            Mail::to($request->user())->send(new OrderConfirmation($order));
        }

        return response()->json(['order' => $order], 201);
    }
}

Same logic. Completely different reading experience. One looks like a ransom note; the other looks like code written by someone who respects their future self.

Pint In Your Git Workflow 🔄

This is where it gets good. In production systems I've built, we run Pint automatically before every commit using a git pre-commit hook. Nobody ships ugly code because nobody can ship ugly code.

The hook setup:

# .git/hooks/pre-commit
./vendor/bin/pint --dirty
git add -u

The --dirty flag only checks files you've actually changed. Nobody wants Pint reformatting 400 files from 2019 during your two-line bug fix.

Or even better — GitHub Actions:

- name: Check code style
  run: ./vendor/bin/pint --test

The --test flag makes Pint report style issues without fixing them — perfect for CI. PR fails if code style is off. No more style debates in reviews. The robot decides. The robot is always right.

Configuring Pint (When Defaults Aren't Enough) 🎛️

Pint uses Laravel's style by default, which is PSR-12 plus some opinionated extras. But you can tweak it with a pint.json in your project root:

{
    "preset": "laravel",
    "rules": {
        "simplified_null_return": true,
        "array_indentation": true,
        "no_unused_imports": true
    }
}

As a Technical Lead, I've learned to keep this file minimal. The more custom rules you add, the more you're just rebuilding the brace wars in JSON format. Trust the defaults. They're good.

Pro Tip: The --dirty Flag Is Your Best Friend 🎯

When you first add Pint to a legacy project (we all have one, don't pretend), running it on the whole codebase creates a 3,000-line diff. Your git blame is ruined. Your team is confused. The blame is now all "style: fix code formatting."

Instead:

# Only fix what's changed since main
./vendor/bin/pint --dirty

# Only fix specific files/folders
./vendor/bin/pint app/Http/Controllers/

# Preview what would change without changing it
./vendor/bin/pint --test

A pattern that saved us in a real project: run pint --dirty in pre-commit hooks, and schedule a separate "style cleanup" PR each sprint to gradually clean up legacy files. You get clean code eventually without torching your git history all at once.

Real Talk: Does Code Style Actually Matter? 💬

Yes. Unironically, yes.

I've onboarded junior developers onto messy codebases and watched them struggle to understand logic that was buried under inconsistent formatting. I've also watched them thrive on clean, consistently-formatted codebases because they could read the code without decoding it first.

Code style isn't about aesthetics. It's about cognitive load. Your brain processes consistently-formatted code faster. You catch bugs faster. You review PRs faster.

And with Pint, the cost of maintaining that consistency is literally one command.

The "But My Editor Already Does This" Argument 🙄

Your editor does it for you. Pint does it for everyone, every time, automatically, in CI. Big difference.

Your editor's settings live on your machine. Your new teammate's editor is configured differently. Your IDE auto-formatter and their IDE auto-formatter have subtle differences. Two months later, every file has been touched by both formatters and the diff is noise.

Pint is the single source of truth. One formatter. One config. Everyone's code looks the same. PR reviews become about logic, not semicolons.

Bonus Tips 🎁

Run Pint on save in VSCode:

// .vscode/settings.json
{
    "emeraldwalk.runonsave": {
        "commands": [
            {
                "match": "\\.php$",
                "cmd": "./vendor/bin/pint ${file}"
            }
        ]
    }
}

Add it to your Makefile:

style:
    ./vendor/bin/pint

style-check:
    ./vendor/bin/pint --test

In Laravel Sail:

sail pint

TL;DR 🚀

  • Install: composer require laravel/pint --dev (or it's already there on Laravel 10+)
  • Fix everything: ./vendor/bin/pint
  • Fix only changed files: ./vendor/bin/pint --dirty
  • Check in CI without fixing: ./vendor/bin/pint --test
  • Config file: pint.json in your project root (keep it minimal)

Stop having code style opinions. Outsource them to Pint. Use the saved mental energy to build features your users actually care about.

Your team will thank you. Your PRs will be shorter. Your onboarding docs will be simpler. And nobody will ever spend 45 minutes arguing about braces again.

I'm speaking from experience. 🙏


Want more Laravel deep dives? Follow me on LinkedIn or star the blog on GitHub.

Now go format that code. 🫧