Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpstan Error Formatter Laravel Package

ticketswap/phpstan-error-formatter

A minimalistic PHPStan error formatter that makes each error a clickable file and line link, avoids wrapping so errors use your full terminal width, highlights variables and class names, and visually truncates long file paths.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install (dev-only):

composer require --dev ticketswap/phpstan-error-formatter

If you already use phpstan/extension-installer (very common in Laravel projects), the extension.neon is registered automatically. If not, add the include manually — forgetting this is the #1 "formatter not found" cause:

includes:
    - vendor/ticketswap/phpstan-error-formatter/extension.neon

2. Look at your phpstan.neon.dist first. That's the only place you need to touch. In a typical Laravel project:

includes:
    - vendor/larastan/larastan/extension.neon

parameters:
    level: 6
    paths:
        - app
        - config
        - routes
        - database
    errorFormat: ticketswap
    editorUrl: 'phpstorm://open?file=%%file%%&line=%%line%%'

Note the formatter name is ticketswap — not ticketswap-error-formatter, not minimal. That's the string you pass to errorFormat.

3. Set editorUrl for your editor (otherwise the clickable links fall back to file:///… paths):

# PhpStorm (global handler registered by the IDE/CLI launcher)
editorUrl: 'phpstorm://open?file=%%file%%&line=%%line%%'

# VS Code
editorUrl: 'vscode://file/%%file%%:%%line%%'

4. Run it:

vendor/bin/phpstan analyse

First use case to try: take your noisiest Laravel module (usually app/Models or app/Http/Controllers) at your current level, run vendor/bin/phpstan analyse app/Models, and click through the output. That single loop — click link, land on the offending line, fix, re-run — is the entire value proposition of this package. If that loop doesn't feel faster than the table formatter after ten errors, don't adopt it.


Implementation Patterns

Shared config, local override. Commit the formatter into phpstan.neon.dist so the whole team gets it, and let individuals tweak via phpstan.neon including the dist file. Don't rely on everyone remembering to add it locally — a formatter nobody enabled does nothing.

CI vs. local split. This formatter is optimised for humans in a terminal: unwrapped errors, per-error clickable links, colour highlighting. In CI you usually want machine annotations instead. The pragmatic pattern:

# phpstan.neon.dist — the human default
parameters:
    errorFormat: ticketswap
# .github/workflows/static.yml
- run: vendor/bin/phpstan analyse --no-progress --error-format=github

The CLI flag wins over the config value, so local runs stay pretty and CI still gets PR annotations. Never parse the human formatter's output in a script — it changes with terminal decoration state (see gotchas). Use --error-format=json or github for anything programmatic.

Focused sub-runs during refactors. Because every error line carries its own file+line, running PHPStan against a narrow path is cheap and useful:

vendor/bin/phpstan analyse app/Domain/Billing

Add Composer scripts for the loops you repeat:

"scripts": {
  "analyse": "phpstan analyse --memory-limit=1G",
  "analyse:changed": "phpstan analyse app/Domain/Billing"
}

Level-ratchet workflow. Bump level one step at a time; use --generate-baseline when the backlog is too big to clear in one PR. The formatter doesn't change baseline semantics at all — it only changes presentation — so it composes cleanly with phpstan-baseline.neon:

vendor/bin/phpstan analyse --generate-baseline

Editor integration. Wire PHPStan into a PhpStorm File Watcher or a VS Code on-save task running vendor/bin/phpstan analyse --no-progress <file>. The clickable-link output makes a narrow-scope, on-save run genuinely pleasant; a full-project run is not.

Splitting identifiers from messages. Modern PHPStan emits error identifiers alongside messages. The formatter prints the identifier when output isn't decorated, which makes it easy to copy into ignoreErrors entries when you're suppressing a rule deliberately rather than fixing it.

AI/agent workflows. Since 1.3.0 the formatter detects AI coding agents via environment variables and stops truncating paths, so an agent sees app/Models/User.php:42 verbatim and can parse it. If you drive PHPStan from a script or agent wrapper, that behaviour is automatic — no config needed.

Vendoring as an escape hatch. The package is essentially a single formatter class plus a NEON file. If you need custom behaviour (JIRA links, different truncation), extending TicketSwapErrorFormatter and registering your own errorFormat name is a realistic afternoon, not a rewrite. Keep that in mind before you reject it for lacking a knob.


Gotchas and Tips

Output differs between terminal and CI. When output is not decorated (piped, redirected, most CI runners), colours and hyperlinks are dropped and the formatter prints the tip and error identifier instead. This is correct behaviour, not a bug — but it means vendor/bin/phpstan analyse > out.txt will not look like your terminal, and any diff-based snapshot test of the output is fragile.

The formatter doesn't prevent terminal wrapping. "Errors don't wrap" means the formatter itself doesn't add a table or hard-wrap columns. If your terminal window is 80 columns wide and the message is 200 characters, your terminal still wraps it and the clickable link can be visually split. Widen the terminal, or use tmux/a wide pane, or accept the wrap. This trips people up because the README oversells it slightly.

Highlighting is deliberately naive. Variables, FQCNs (including leading-slash and comma-adjacent forms), stdClass, Stringable, and Class::CONSTANT are matched by regex. FQCN-looking strings inside quoted literals and heredocs get coloured too. Treat colour as a hint, never as parsed data. Don't file bugs for mis-highlighting unless it's actively misleading.

Line 0 errors print no line number. Config errors, "ignored error pattern was not matched", and file-level problems have no meaningful line; since 1.2.5 the line is omitted entirely. If you're hunting for "line 1", stop — there is none.

Path truncation breaks copy-paste. Paths render like src/App/../Entity/User.php — visually shortened, link intact. In shells where you'd normally copy the path out, that's annoying. Newer versions skip truncation entirely when an AI agent is detected. If neither behaviour suits you, that's the point to fork or override the formatter class.

editorUrl needs doubled percent signs in NEON. %%file%% and %%line%%, not %file%. A single % will make NEON try to resolve a parameter and fail with a confusing parse error.

Relative vs. absolute paths. PHPStan reports paths relative to the working directory unless you set editorUrl. Links derived from relative paths work in some terminals and not others. Setting editorUrl explicitly with your editor's URI scheme is the reliable option — do it rather than relying on the file:/// fallback.

Docker / Sail breaks OSC 8 links. Running PHPStan via docker compose exec app ./vendor/bin/phpstan analyse can strip the terminal hyperlink sequences or produce file:///var/www/html/... paths that don't exist on your host. Either run PHPStan on the host (with a host-compatible autoloader/container) or accept plain paths and use your IDE's "go to file" instead.

PHPStan 2 compatibility landed in 1.1.4. If you're on PHPStan 2.x, pin ^1.3 (or at least ^1.1.4); older tags will fail on version constraints. Also check the PHP floor — the package settled on PHP 8.1+ after some back-and-forth in early releases, so PHP 7.4 projects are out of luck.

Windows support only arrived in 1.2.5. Older versions mangle path separators and links. If you have Windows developers, don't let a stale lockfile pin them below that.

Missing include = cryptic failure. Without phpstan/extension-installer and without the manual includes: entry, PHPStan complains about an unknown errorFormat. The message doesn't always say "you forgot the extension include", so check that first.

Extension points are thin, by design. There's no config for colours, no truncation length setting, no severity mapping. What you get is what you get. If you need any of that, register a second formatter name in your own extension NEON pointing at a subclass — don't try to bend this package's config.

Vendor risk assessment. 87 stars, zero listed dependents, effectively a one-maintainer TicketSwap project. Mitigations: MIT licence, tiny surface area (one formatter class + one NEON file), and it's easy to vendor-copy into app/Support/Phpstan/ if it's ever abandoned. Treat it as an optional DX nicety, not infrastructure — never let your build depend on it being available.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route