Skip to main content

🧩 Usage

After installing the package, run the linter on all migrations:

php artisan migrate:lint

This scans your database/migrations folder for risky schema operations and reports potential issues.


βš™οΈ Command Options​

You can customize the linting behavior using the following flags and options:

Option / FlagDescription
--generate-baselineCreate a baseline JSON file (migration-linter-baseline.json) that records current issues, allowing you to ignore them in future runs (useful when introducing the linter to legacy projects).
--path=Lint a specific file or directory instead of the default database/migrations folder.
--jsonOutput results in structured JSON format (ideal for CI/CD or automation).
--html=Generate an interactive HTML report. If no path specified, defaults to storage/app/migration-lint-report.html.
--baseline=Provide a custom path to a baseline file (overrides the default baseline file).
--compactDisplay a shorter, condensed table layout for smaller terminals or narrow CI logs.
--rulesView all rules and their enabled statuses.
--summaryDisplay summary footer in output.
--no-suggestionsHide migration suggestions from output (show only the warnings table).

πŸ’» Example Commands​

πŸ” Lint all migrations​

php artisan migrate:lint

🧾 Generate a new baseline file (ignore current issues)​

php artisan migrate:lint --generate-baseline

This creates migration-linter-baseline.json in your project root.


πŸ“‚ Lint a specific path​

php artisan migrate:lint --path=database/migrations/2025_10_20_123456_create_users_table.php

🧠 Export report as JSON (for CI pipelines)​

php artisan migrate:lint --json > storage/lint-report.json

Example output (simplified):

[
{
"rule": "DropColumnWithoutBackup",
"severity": "warning",
"message": "Dropping column 'age' from table 'users' may result in data loss.",
"file": "2025_10_20_123456_update_users_table.php",
"line": 15,
"suggestion": "Back up data before dropping. Consider renaming with suffix '_old'.",
"docs_url": "https://...docs/rules#-dropcolumnwithoutbackup"
}
]

Note: JSON output now includes suggestion and docs_url fields for easy integration with CI/CD tools.​

πŸ—‚ Use a custom baseline file​

php artisan migrate:lint --baseline=storage/custom-baseline.json

πŸ—‚ List all rules with their enabled statuses​

php artisan migrate:lint --rules

Example output:

πŸ“‹ Available Migration Linter Rules

+--------------------------------------------+----------+---------------------------------------------------------------+
| Rule ID | Enabled | Description |
+--------------------------------------------+----------+---------------------------------------------------------------+
| AddNonNullableColumnWithoutDefault | Yes | Warns when adding a NOT NULL column without a default value. |
| MissingIndexOnForeignKey | No | Detects missing indexes on foreign key columns. |
| DropColumnWithoutBackup | Yes | Warns when columns are dropped without backup. |
| AddUniqueConstraintOnNonEmptyColumn | No | Warns when adding unique constraints on existing data. |
| FloatColumnForMoney | Yes | Warns when float() used for monetary values. |
+--------------------------------------------+----------+---------------------------------------------------------------+

πŸ—‚ Display Summary in output​

php artisan migrate:lint --summary

Example output includes a summary section with total files scanned, issue counts by severity, and overall status.


🎨 Hide Suggestions (cleaner output)​

php artisan migrate:lint --no-suggestions

This displays only the warnings table without the detailed migration suggestions. Useful when you're familiar with the issues and want a compact view.

Combine flags for customized output:

# Table only (no suggestions, no summary)
php artisan migrate:lint --no-suggestions

# Table + summary (no suggestions)
php artisan migrate:lint --summary --no-suggestions

# Full report with everything (default)
php artisan migrate:lint --summary

Note: Suggestions are grouped by rule type to avoid repetition. If you have multiple violations of the same rule, the suggestion is shown only once with an occurrence count.


πŸ“Š Example Output (with grouped suggestions)​

php artisan migrate:lint --summary

Example output:

⚠️  Lint Report

+--------------------------------+-------------------------------+--------+----------+--------------------------------+
| File | Rule | Column | Severity | Message |
+--------------------------------+-------------------------------+--------+----------+--------------------------------+
| 2024_01_15_create_orders.php | ChangeColumnTypeOnLargeTable | price | error | Changing column type with ->c… |
| 2024_01_15_create_orders.php | ChangeColumnTypeOnLargeTable | status | error | Changing column type with ->c… |
| 2024_01_20_rename_user.php | RenamingColumnWithoutIndex | name | warning | Renaming column 'old_name' to… |
+--------------------------------+-------------------------------+--------+----------+--------------------------------+

πŸ’‘ Suggestions & Recommendations
════════════════════════════════════════════════════════════

πŸ“‹ ChangeColumnTypeOnLargeTable (2 occurrences)
────────────────────────────────────────────────────────────
**Recommended Migration Strategy:**

βœ… **Option 1: Zero-Downtime Multi-Step Migration**
[Detailed migration steps with code examples...]

⚠️ **Option 2: Maintenance Window**
[Alternative approach...]

πŸ“– Documentation: https://docs.example.com/...

πŸ“‹ RenamingColumnWithoutIndex (1 occurrence)
────────────────────────────────────────────────────────────
[3-phase zero-downtime strategy...]
πŸ“– Documentation: https://docs.example.com/...

πŸ“Š Summary
───────────────────────────────────
🧩 Total Files Scanned: 3
πŸ” Issues Found: 3
⚠️ Warnings: 1
❌ Errors: 2
πŸ’‘ Info: 0

[WARNING] ⚠️ Some migrations contain potential risks.

Key Features:

  • Grouped Suggestions β€” Same rule violations show suggestion only once with occurrence count
  • Visual Hierarchy β€” Clear sections with proper separators (═ and ─)
  • Color Coding β€” Cyan for rules, blue for docs, severity-based colors
  • Minimal Repetition β€” Clean, professional output

πŸ–₯ Compact mode for smaller terminals​

php artisan migrate:lint --compact

This outputs a shorter version of the table without verbose file paths.


🚦Exit Codes​

Exit CodeMeaningWhen it occurs
0βœ… No critical issues (or only warnings below threshold)Safe to proceed
1❌ One or more rules exceeded the severity thresholdCI/CD should fail

The threshold is controlled by severity_threshold in your configuration file. For example, setting 'severity_threshold' => 'error' will fail the command only when error-level issues are found.


οΏ½ Understanding Suggestions​

Each warning includes actionable suggestions to help you fix the issue. When you run php artisan migrate:lint, you'll see:

  1. The Warning Table β€” Shows all issues with severity and details
  2. Suggestions Section β€” Detailed fix recommendations below the table

Example:

⚠️  Lint Report
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ File β”‚ Rule β”‚ Column β”‚ Severity β”‚ Message β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ create_users β”‚ AddNonNullableColumnWi... β”‚ email β”‚ warning β”‚ Adding NOT β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ NULL... β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

[Suggestion #1] AddNonNullableColumnWithoutDefault:
Option 1: Add a default value:
$table->string('email')->default('')->nullable(false);

Option 2: Make it nullable, then alter:
$table->string('email')->nullable();
DB::table('users')->update(['email' => '...']);
$table->string('email')->nullable(false)->change();

πŸ“– Learn more: https://...docs/rules#-addnonnullablecolumnwithoutdefault

For JSON output, suggestions are included in each issue object for programmatic access.


οΏ½πŸ’‘ Pro Tips​

  • Use --generate-baseline once when introducing the linter to a legacy codebase, then commit the baseline file.
  • Regularly re-run php artisan migrate:lint in your CI/CD to catch unsafe schema changes early.
  • Combine with your existing testing jobs to prevent migration issues from reaching production.
  • Each warning includes actionable suggestions β€” follow them to fix issues quickly.
  • JSON output includes suggestions and documentation links β€” integrate with your tools!

βœ… That's it! You're ready to lint, baseline, and enforce migration safety across all environments.