tightenco/tlint
Tighten’s opinionated linter for Laravel and PHP projects. Enforces consistent conventions and catches style issues using preset and custom rules, runnable via CLI or CI. Built on PHP_CodeSniffer with sensible Laravel-focused defaults.
Installation:
composer require --dev tightenco/tlint
Add to composer.json under require-dev:
"tightenco/tlint": "^9.6"
Configuration:
Create tlint.json in your project root:
{
"presets": ["tighten"],
"paths": ["app", "config", "routes"]
}
First Run:
vendor/bin/tlint
This runs all linters in the tighten preset against specified paths.
Run TLint as a pre-commit hook to enforce conventions before code is committed:
# Add to package.json (if using npm scripts)
"scripts": {
"lint": "tlint"
}
Or integrate with Git hooks (e.g., husky):
npx husky add .husky/pre-commit "vendor/bin/tlint"
Daily Linting: Run TLint in CI/CD pipelines (e.g., GitHub Actions) to catch violations early:
# .github/workflows/lint.yml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install
- run: vendor/bin/tlint
Selective Linting: Target specific linters or files:
# Run only the `FullyQualifiedFacades` linter
vendor/bin/tlint --only FullyQualifiedFacades
# Lint a single file
vendor/bin/tlint app/Http/Controllers/UserController.php
Custom Presets:
Extend the tighten preset in tlint.json:
{
"presets": ["tighten"],
"linters": {
"NoDump": {
"enabled": true,
"allow": ["dd", "dump", "ray"]
}
}
}
Formatter Integration:
Use formatters to auto-fix issues (e.g., FullyQualifiedFacades):
vendor/bin/tlint --format
barryvdh/laravel-ide-helper to auto-generate facades for FullyQualifiedFacades.vendor/bin/tlint--format $FilePath$$ProjectFileDir$PHP Intelephense extension with TLint’s checkstyle output:
// .tlint.json
{
"reporting": {
"checkstyle": true
}
}
False Positives:
NoDump linter may flag dd() or dump() calls. Exclude them in config:
"linters": {
"NoDump": {
"allow": ["dd", "dump"]
}
}
OneLineBetweenClassVisibilityChanges may fail with complex comments. Use --ignore to skip files:
vendor/bin/tlint --ignore app/Models/ComplexModel.php
Performance:
storage/, vendor/) in tlint.json:
"paths": ["app", "config"],
"ignore": ["**/tests/**", "**/storage/**"]
vendor/bin/tlint --parallel
Breaking Changes:
AlphabeticalImports). Update your config if relying on them.tformat.json in favor of tlint.json. Merge configs if upgrading.Verbose Output:
vendor/bin/tlint -v
Reveals skipped files and linter details.
Dry Run:
vendor/bin/tlint --dry-run
Shows what would be fixed without modifying files.
Custom Linters:
Extend Tighten\TLint\Linter to create reusable linters:
namespace App\TLint;
use Tighten\TLint\Linter;
class CustomLinter extends Linter {
protected $message = 'Custom rule violated';
public function lint($node) {
// Logic here
}
}
Register in tlint.json:
"linters": {
"CustomLinter": {
"class": "App\\TLint\\CustomLinter"
}
}
Formatter Overrides:
Override default formatters (e.g., FullyQualifiedFacades) by extending Tighten\TLint\Formatter:
namespace App\TLint;
use Tighten\TLint\Formatter;
class CustomFacadeFormatter extends Formatter {
public function format($node) {
// Custom logic
}
}
Reporting: Generate custom reports (e.g., JUnit for CI):
"reporting": {
"checkstyle": true,
"output": "build/report.xml"
}
FullyQualifiedFacades to enforce use Illuminate\Support\Facades\Log; instead of use Log;.SpaceAfterBladeDirectives). Add Blade paths:
"paths": ["resources/views"]
- run: vendor/bin/tlint || exit 1
How can I help you explore Laravel packages today?