skip to content

What is Laravel Pint, and how do you run it to fix the code style of a Laravel application?

level: juniorimportance: must knowfreq 55%

answer

  1. opinionated fixer, zero configuration
  2. a wrapper around PHP CS Fixer
  3. ./vendor/bin/pint from the project root
  4. laravel preset unless told otherwise
  5. -v prints each file's diff

basics

~20 s

Laravel Pint is an opinionated PHP code style fixer built on PHP CS Fixer and shipped as a dev dependency of new Laravel apps. Running ./vendor/bin/pint rewrites your PHP files to the laravel preset; adding --test only reports.

solid answer

~40 s

Laravel Pint is a zero-configuration code style fixer that wraps PHP CS Fixer with Laravel's own rule preset. The Laravel 13 skeleton already lists `laravel/pint` in `require-dev`, so you run `./vendor/bin/pint` from the project root and it rewrites every `.php` file it finds to the `laravel` preset, skipping `vendor`, `storage`, `node_modules`, `bootstrap/cache` and `build`. Blade templates are left alone unless you opt in. You can narrow a run to paths (`./vendor/bin/pint app/Models`), add `-v` to print the diff of every change, or add `--test` to report problems without writing anything, which exits non-zero when a file would change. A `pint.json` in the project root is optional: you only need one to change the preset, rules or excluded paths.

code

bash · 3 lines
bash
./vendor/bin/pint
./vendor/bin/pint app/Models/User.php -v
./vendor/bin/pint --test

go deeper

for a junior

Recall the binary path, that it fixes files in place with the laravel preset, and that --test only reports. Mention it is already installed in new Laravel apps.

for a middle

Explain that Pint is PHP CS Fixer plus a preset and defaults, what it skips by default, and why plain pint exits 0 after fixing while --test fails on drift.

for a senior

Talk about where Pint runs in a team: editor, pre-commit hook and a CI --test gate, and how you keep formatting commits out of feature diffs.

for a principal

Frame Pint as removing style debates from review: the value is one agreed preset applied by a tool, so reviewers spend attention on behaviour instead of whitespace.

## What Laravel Pint is **Laravel Pint** is a code style fixer for PHP maintained by the Laravel team. A *code style fixer* reads source files and rewrites their layout: spacing, brace placement, import order, quote style, blank lines, unused `use` statements. It aims to change layout rather than behaviour, and it does not look for bugs or type errors; that is the job of a static analyser. Pint is **built on PHP CS Fixer**, the long-standing PHP fixer engine. Pint's contribution is the packaging around that engine: - a ready-made **`laravel` preset** that encodes the style the framework itself is written in; - **zero configuration**: no config file is needed before the first run; - a small set of Laravel-flavoured command-line options (`--test`, `--repair`, `--dirty`, `--diff`, `--parallel`) and a terse, readable summary; - an optional `pint.json` file when you want to change the preset, individual rules or the files it inspects. It is **opinionated**: the point is that a team stops debating style and lets one tool decide. ## Getting it and running it The Laravel 13 application skeleton lists `laravel/pint` in `require-dev` of `composer.json`, so a new app already has it after `composer install`. An older app adds it with `composer require laravel/pint --dev`. Because it lives in `require-dev`, a production install with `composer install --no-dev` does not ship it, which is what you want for a development tool. A typical first session looks like this: 1. Run `./vendor/bin/pint` from the project root. Pint scans the project, fixes every file that breaks the preset and prints a summary listing the files it changed. 2. Run `./vendor/bin/pint -v` when you want to see *what* changed; the verbose flag prints a diff per file. 3. Run it on part of the tree by passing paths: `./vendor/bin/pint app/Models` or `./vendor/bin/pint app/Models/User.php`. 4. Run `./vendor/bin/pint --test` when you only want to know whether anything is wrong. Nothing is written, and the exit code is non-zero if any file would change. ```bash ./vendor/bin/pint # fix the whole project ./vendor/bin/pint app/Models -v # fix one folder and show diffs ./vendor/bin/pint --test # report only; non-zero exit on drift ``` ## What a run touches by default With no configuration, Pint inspects `.php` files under the current directory and skips: - the `vendor` directory; - `storage`, `node_modules`, `bootstrap/cache` and `build`; - dot files and version-control folders; - generated IDE helper files such as `_ide_helper.php` and `.phpstorm.meta.php`; - Blade templates (`*.blade.php`), unless the `Pint/laravel_blade` rule is enabled in `pint.json` or the `--blade` option is passed for one run. The Blade rule is worth a note: it formats templates through Prettier with Blade and Tailwind plugins, so it needs Node.js on the machine, and Pint offers to install the missing packages on first use. ## Fix mode versus check mode | Command | Writes files | Exit code | |---|---|---| | `./vendor/bin/pint` | yes | 0 after fixing, unless a file could not be parsed or fixed | | `./vendor/bin/pint -v` | yes | same, plus a diff per file | | `./vendor/bin/pint --test` | no | non-zero when any file would change | The first row surprises people: plain `pint` succeeds even when it rewrote fifty files, because fixing is the job it was asked to do. That is why a build gate uses `--test` and never plain `pint`. ## Where Pint fits - It enforces **layout**, not correctness. A formatted file can still be full of bugs. - It runs the **`laravel` preset** by default; `per`, `psr12`, `symfony` and `empty` are the alternatives, chosen in `pint.json` or with `--preset`. - The rule names it understands are PHP CS Fixer's rules, plus a few custom rules prefixed `Pint/`. - It is usually wired into three places: a developer's editor or terminal, a pre-commit hook, and a CI job that runs `--test`. The summary is worth reading rather than skimming. For each file it lists the names of the rules that fired, such as `ordered_imports` or `concat_space`, so after a few runs you know the preset well enough to write code that needs no fixing. When a file cannot be parsed, the summary shows the error instead of a rule list, and the run fails. For a junior developer, the practical habit is simple: run `./vendor/bin/pint` before you push, and read the list of files it changed so that formatting never hides inside a feature diff.

  • Does a plain ./vendor/bin/pint run fail a build when it had to fix files?
    No. Fix mode exits 0 after rewriting files; it only fails on errors such as a file it cannot parse. To gate a build you use `--test`, which exits non-zero when anything would change, or `--repair`, which fixes the files and still exits with status 1.
  • Does Pint format Blade templates as well as PHP classes?
    Not by default: files ending in `.blade.php` are skipped. Enabling the `Pint/laravel_blade` rule in `pint.json`, or passing `--blade` for a single run, makes Pint format them through Prettier with Blade and Tailwind plugins, which requires Node.js.
  • Why does laravel/pint sit in require-dev rather than require?
    Pint is only needed while writing and checking code, never while serving requests. Keeping it in `require-dev` means a production install with `composer install --no-dev` leaves it out, so the deployed app carries less code.

saying these in an interview costs you the question

  • Pint finds bugs and type errors the way a static analyser does.
  • Pint refuses to run until you create a pint.json file.
  • Plain pint only reports problems; you need a flag before it fixes anything.
  • Pint applies PSR-12 by default in a Laravel project.
  • Pint also reformats the packages inside vendor.