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

Tighten Coding Standard Laravel Package

tightenco/tighten-coding-standard

Tighten Coding Standard is an opinionated PHP_CodeSniffer ruleset for Laravel projects, enforcing consistent code style and catching common issues with minimal configuration. Install it via Composer and run it against your codebase.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register the standard. It is a dev-only dependency, so keep it out of production builds:

composer require --dev tightenco/tighten-coding-standard

PHPCS discovers third-party standards through installed_paths, which is normally handled by dealerdirect/phpcodesniffer-composer-installer. If your Composer 2.2+ project has no allow-list entry yet, add it once:

"config": {
    "allow-plugins": {
        "dealerdirect/phpcodesniffer-composer-installer": true
    }
}

Confirm the standard is actually visible before writing any config. This is the single most important two seconds of the install:

vendor/bin/phpcs -i
# expect: The installed coding standards are PSR12, Tighten, ...

If Tighten is missing there, nothing you do in phpcs.xml will enforce anything — see the "false green" gotcha below.

Write a phpcs.xml at the repo root, scoping it to your Laravel source and excluding the noise directories PHPCS should never walk:

<?xml version="1.0"?>
<ruleset name="App">
    <description>App coding standard</description>

    <file>app</file>
    <file>config</file>
    <file>database</file>
    <file>routes</file>
    <file>tests</file>

    <exclude-pattern>*/vendor/*</exclude-pattern>
    <exclude-pattern>*/storage/*</exclude-pattern>
    <exclude-pattern>*/bootstrap/cache/*</exclude-pattern>
    <exclude-pattern>*/node_modules/*</exclude-pattern>
    <exclude-pattern>_ide_helper*.php</exclude-pattern>

    <arg name="extensions" value="php"/>
    <arg name="parallel" value="8"/>
    <arg name="colors"/>

    <rule ref="Tighten"/>
</ruleset>

First use case: audit, don't enforce. Point it at a single directory on day one and read the summary report rather than wiring up CI:

vendor/bin/phpcs app/Http/Controllers --report=summary

That gives you a violation count per sniff — which is effectively your debt estimate, and tells you which sniffs you'll want to argue about before the team sees them in a failing pipeline.

Where to look first when something surprises you. Read the package's own ruleset.xml inside vendor/tightenco/tighten-coding-standard/ — that file is the documentation. It lists every referenced sniff and any custom sniffs the package ships. When a rule fires and you don't understand why, run phpcs -s to print the sniff code, then grep that code in the ruleset.

Implementation Patterns

Wire it into Composer scripts so it's one memorable command, not a URL in a wiki.

"scripts": {
    "lint": "phpcs",
    "lint:fix": "phpcbf",
    "lint:summary": "phpcs --report=summary",
    "test": ["@lint", "@php artisan test"]
}

Developers reach for composer lint reflexively; they do not reach for vendor/bin/phpcs -q --parallel=8.

Split detection from formatting. PHPCS's phpcbf auto-fixer coverage is uneven — it will fix whitespace and some structural issues but leaves most docblock and naming opinions untouched. Treat phpcs as the gate and phpcbf as a convenience. Run phpcbf only on files you already touched, and review its diff like any other code change:

vendor/bin/phpcbf app/Services/BillingService.php
git diff app/Services/BillingService.php

Adopt on changed files first, not the whole tree. A full-tree run on a legacy app produces a thousand-line diff, destroys git blame, and blocks every open branch. Two workable patterns:

  • Changed-files gating: compute the diff against the target branch and pass only those paths to phpcs in CI.
  • Baseline freezing: generate a report of current violations once, commit it, and only fail on violations not in the baseline. Shrink the baseline directory by directory as a recurring maintenance task.

Either way, the whole-tree phpcbf sweep happens last, as its own no-functional-change PR, in a quiet branch window. It's the only irreversible artifact in the rollout.

Decide the formatter of record before you install anything. Most Laravel shops already run Pint, which is PHP-CS-Fixer based, and running both produces overlapping opinions and conflicting auto-fixes. The pragmatic split:

  • Pint owns formatting (whitespace, imports, spacing, braces) — it's the auto-fixer.
  • PHPCS owns the structure and documentation opinions Pint doesn't have.

Practically: run Pint first, then PHPCS, and let Pint's opinion win on the overlapping sniffs by excluding the formatting-only sniffs from your phpcs.xml:

<rule ref="Tighten">
    <exclude name="Generic.Files.LineLength"/>
    <!-- plus whichever formatting sniffs your Pint preset already covers -->
</rule>

Reversing this decision later means re-normalizing the whole tree, so make it explicit.

Distribute the standard to editors, or you will fight "it passed on my machine" forever. Commit phpcs.xml, pin the package version in composer.lock, and point the editor plugin at the project-local binary — never a globally installed phpcs. In VS Code:

{
    "phpcs.executablePath": "vendor/bin/phpcs",
    "phpcs.standard": "phpcs.xml"
}

For CI, emit a machine-readable report so failures land inline on the diff rather than as anonymous console noise:

vendor/bin/phpcs --report=checkstyle --report-file=build/phpcs.xml

Use phpcs.xml.dist for team scaffolding, phpcs.xml for local escape hatches. PHPCS prefers phpcs.xml when both exist, so the .dist file is your shared baseline and any developer can create an untracked phpcs.xml to silence a sniff they're experimenting with — without polluting the shared config.

Fork deliberately if you're going to diverge. The package's weakness is that it has essentially no upstream adoption. Copy the ruleset into your repo, own it, and pin the dependency. If you need custom sniffs of your own, add them alongside and reference them by path:

<rule ref="./tools/phpcs/Standards/App/Sniffs"/>

That converts an external maintenance risk into a one-time setup cost you control.

Document suppressions with a reason, every time. Treat inline suppressions as reviewable code:

// phpcs:ignore Tighten.Sniffs.SomeSniff -- legacy API contract, see TICKET-412

Track the suppression-comment count as a metric. A slow creep of phpcs:ignore lines is how a standard dies.

Gotchas and Tips

Beware the false green — this is the highest-severity failure mode. If the standard fails to register, PHPCS may error out or, worse, run against an effectively empty ruleset while your pipeline reports success. Teams have shipped green builds that enforced nothing. Mitigate with a committed known-bad fixture that CI must reject:

# tests/fixtures/phpcs/known-violation.php contains a deliberate violation
vendor/bin/phpcs tests/fixtures/phpcs/known-violation.php \
  && { echo "PHPCS failed to flag a known violation"; exit 1; } || true

Assert on the sniff code, not just the exit status, so a silently missing sniff is caught too.

The Composer plugin allow-list bites twice. Adding dealerdirect/phpcodesniffer-composer-installer to one project's composer.json doesn't help the shared CI image, the other services, or the Docker build. If PHPCS reports Referenced sniff "Tighten" does not exist in CI but works locally, the plugin wasn't allowed in that environment. Audit every pipeline that runs PHP, not just the pilot.

Pin squizlabs/php_codesniffer to a minor version. Sniffs track PHP tokenizer behavior, and PHPCS 4.x is a breaking release for standards authors. New language features — enums, readonly properties, attributes, first-class callables — have historically produced false positives until sniffs catch up. Pin, read the changelog on every bump, and gate upgrades behind your known-bad fixture. If composer update silently moves PHPCS across a major, your gate may stop working without anyone noticing.

Expect noise from the docblock and naming sniffs before you expect agreement. The ruleset encodes one consultancy's house style — docblock-heavy, opinionated Laravel. Review the full rule list before enabling a blocking gate, and disable anything the team won't defend in code review. A rule nobody will defend becomes a suppression comment nobody reviews, which is worse than not having the rule.

--parallel is worth the configuration. PHPCS is single-threaded by default and noticeably slow on a large app/ tree. Set <arg name="parallel" value="8"/> in phpcs.xml or pass -p --parallel=8. Also make sure you're excluding vendor, storage, node_modules, and generated files — walking vendor/ alone can multiply your CI wall-clock by a factor of ten.

Don't run it on Blade templates. Without a Blade-specific sniffer, pointing PHPCS at resources/views produces garbage output. Scope <file> entries to PHP source only.

A pre-commit hook that runs phpcs over the whole tree will be disabled within a week. Either scope it to staged files (phpcs $(git diff --cached --name-only --diff-filter=ACM | grep '\.php$')) or skip the hook entirely and rely on CI. A fast, narrow hook survives; a slow, broad one doesn't.

"It passed locally" usually means a version mismatch, not a lie. The editor plugin is running a globally installed phpcs, or a different standard, or a stale installed_paths cache. Have developers run vendor/bin/phpcs --version and vendor/bin/phpcs -i when a CI-only failure appears — that resolves it nine times out of ten. composer dump-autoload after changing installed_paths is sometimes necessary; you can also clear the PHPCS cache with --no-cache to rule that out.

Assume you are the maintainer. Zero stars, zero dependents, v1.0.2 as the visible ceiling. There will be no community triage for your PHP version, no knowledge base, no expectation that an edge case gets fixed upstream. Budget a few hours per PHP minor upgrade to validate against your fixture, name an owner for phpcs.xml and the baseline, and treat the upstream repo as reference material rather than a supported dependency. Don't depend on it unpinned if your platform upgrade cadence is aggressive.

Keep it out of production artifacts. require-dev plus --no-dev in release builds handles it, but add an assertion to the build so it can't regress — a stray composer install in a Dockerfile will happily ship PHPCS and every sniff to your runtime image.

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log