laravel-migralign maintained by migralign
Table of contents
- Overview
- Features
- Requirements
- Installation
- Quick start
- How MigrAlign works
- Risk model and behavior
- Command reference
- Configuration
- Recommended workflows
- Examples
- Limitations
- Troubleshooting
- FAQ
- Publish to Packagist
- GitHub deployment guide
- Contributing
- License
Overview
MigrAlign compares your Laravel migration-defined schema with the current MySQL/MariaDB schema and helps you synchronize differences safely.
It is useful when:
- schema drift appears between migration files and real database state
- teams edit migrations and need a deterministic sync pass
- you want safe automation for additive/low-risk changes with explicit handling for risky changes
Features
- Scans migration intent from
Schema::create()andSchema::table() - Introspects live schema from
information_schema - Computes table/column diffs
- Auto-applies safe changes
- Interactively prompts for risky/destructive changes
- Supports targeted sync by table or migration filename
- Supports dry-run preview and force mode
- Prints final sync report (
applied,skipped,pending manual,errors)
Requirements
- PHP 8.2+
- Laravel 11, 12, or 13
- MySQL or MariaDB connection
- PHP 8.3+ required when using Laravel 13
Installation
Install the package:
composer require migralign/laravel-migralign
Publish config (optional):
php artisan vendor:publish --tag=migralign-config
This creates:
config/migralign.php
Quick start
- Update your migration files.
- Preview what would change:
php artisan migralign:sync --dry-run
- Apply sync:
php artisan migralign:sync
How MigrAlign works
- Scan migration files from
config('migralign.migrations_path') - Build expected schema intent from migration
up()logic - Read live schema from MySQL
information_schema - Compute diff for tables and columns
- Classify risk for each change
- Apply safe changes automatically (if enabled)
- Prompt for risky changes (or skip/apply/abort)
- Print report
Risk model and behavior
MigrAlign classifies each change into one of:
saferiskydestructive
Usually safe
- add nullable columns
- widen certain column sizes
- non-destructive metadata-level changes
Usually risky
- shrinking type/length (example:
VARCHAR(255)->VARCHAR(50)) - nullable -> not nullable
- enum contractions
- type family changes with potential conversion problems
Usually destructive
- drop column
- drop table
For risky/destructive changes, MigrAlign shows:
- why the change is risky
- optional pre-check query
- suggested remediation SQL/instructions
- interactive choice: apply / skip / abort
Command reference
Main command
php artisan migralign:sync
Options
-
--dry-run
Show planned changes only, do not apply. -
--force
Apply risky changes without interactive prompts. -
--table=users
Limit sync to a specific table. -
--migration=create_users
Scan only migrations with matching filename text. -
--connection=mysql
Override DB connection used for introspection/apply.
Typical command examples
# Preview everything
php artisan migralign:sync --dry-run
# Sync only users table
php artisan migralign:sync --table=users
# Preview a subset of migrations
php artisan migralign:sync --dry-run --migration=2024_01_01
# Apply all including risky (no prompts)
php artisan migralign:sync --force
Configuration
Default config file:
return [
'migrations_path' => database_path('migrations'),
'ignored_tables' => [
'migrations',
'password_reset_tokens',
'sessions',
'cache',
'cache_locks',
'jobs',
'job_batches',
'failed_jobs',
],
'auto_apply_safe' => true,
'connection' => null,
];
Config keys
-
migrations_path
Path to migration files used to build expected schema. -
ignored_tables
Tables excluded from diffing. -
auto_apply_safe
Iftrue, safe changes apply automatically. -
connection
Default DB connection.nullmeans Laravel default.
Recommended workflows
Workflow A: Add a new column
When you add a column in migrations (Schema::create() or Schema::table()):
php artisan migralign:sync --dry-run
php artisan migralign:sync
If the column is nullable or otherwise safe, it is created automatically.
Workflow B: Risky schema tightening
For changes like nullable(true) -> nullable(false) or length shrink:
- run
--dry-run - review pre-checks and remediation
- backfill/clean data if needed
- run sync and confirm prompts
Workflow C: CI safety preview
Use dry-run in CI/CD to detect unexpected drift:
php artisan migralign:sync --dry-run
Examples
Example 1: New nullable column
Migration:
Schema::table('users', function (Blueprint $table) {
$table->string('phone', 20)->nullable();
});
Result:
- Diff includes
add_columnforusers.phone - Sync applies it automatically (safe)
Example 2: Column removed from migration intent
If a column exists in DB but not in migration intent:
- diff includes
drop_column - classified as destructive
- prompt asks whether to apply/skip/abort
Example 3: Not-null tightening
Migration intent changes nullable column to not nullable:
- diff includes
modify_column - risky classification
- pre-check identifies violating rows when applicable
Limitations
- Current support target is MySQL/MariaDB only
- Migration scanning executes migration
up()logic in recording mode; extremely dynamic migration logic may need extra care - Destructive actions should always be reviewed in dry-run first
Troubleshooting
"supports MySQL/MariaDB only"
Your selected connection is not MySQL/MariaDB.
Use --connection= with a MySQL connection, or set migralign.connection.
No differences found but you expect changes
- verify migration file is inside
migralign.migrations_path - verify
--migration=filter is not excluding it - ensure target table is not in
ignored_tables
Risky change is blocked or skipped
- run with
--dry-runfirst - follow remediation instructions
- fix data inconsistencies
- run again, or use
--forceif you explicitly accept the risk
FAQ
Should I edit old historical migrations?
Prefer adding new migrations for forward changes.
Editing old migrations can create large drift expectations across environments.
Is this a replacement for php artisan migrate?
No. migrate applies migration history; MigrAlign aligns current schema intent to live schema through diff + risk controls.
Can I use this in production?
Yes, but always run dry-run first and review destructive/risky operations.
Publish to Packagist
Follow these steps to publish MigrAlign on Packagist so anyone can install it with Composer.
Prerequisites
- GitHub repository is public: mokhdesigns/laravel-migralign
composer.jsonhas a valid"name":migralign/laravel-migralign- At least one git tag is pushed (recommended:
v1.0.0)
git tag -a v1.0.0 -m "MigrAlign v1.0.0"
git push origin v1.0.0
Step 1 — Create a Packagist account
- Open https://packagist.org/register/
- Register and confirm your email
- Sign in at https://packagist.org/
Step 2 — Submit the package
-
Click Submit in the top menu (or go to packagist.org/packages/submit)
-
Paste the repository URL:
https://github.com/mokhdesigns/laravel-migralign -
Click Check — Packagist reads
composer.jsonfrom the default branch -
Confirm the detected package name is
migralign/laravel-migralign -
Click Submit
Your package page will be:
https://packagist.org/packages/migralign/laravel-migralign
Step 3 — Enable automatic updates (recommended)
Without auto-update, you must click Update on Packagist after every new tag.
Option A — GitHub webhook (easiest)
- Open your package on Packagist → Settings (or profile → GitHub)
- Connect your GitHub account if not already connected
- Enable the GitHub Service Hook / Auto-update for
mokhdesigns/laravel-migralign - Packagist will refresh when you push new tags to GitHub
Option B — Manual update
- Open packagist.org/packages/migralign/laravel-migralign
- Click Update after each release
Step 4 — Verify installation
In a fresh Laravel project (MySQL configured):
composer require migralign/laravel-migralign
php artisan vendor:publish --tag=migralign-config
php artisan migralign:sync --dry-run
Install a specific version:
composer require migralign/laravel-migralign:^1.0
Step 5 — Publish new versions
For each release:
# commit changes on main
git tag -a v1.0.1 -m "MigrAlign v1.0.1"
git push origin v1.0.1
Then either wait for the GitHub hook or click Update on Packagist.
Packagist checklist
- Repository is public on GitHub
-
composer.jsonname ismigralign/laravel-migralign - Tag
v1.0.0(or latest) exists on GitHub - Package submitted on Packagist
- GitHub auto-update hook enabled
-
composer require migralign/laravel-migralignworks in a test app
Troubleshooting Packagist
| Issue | Solution |
|---|---|
| Package not found after submit | Wait 1–2 minutes; run composer clear-cache |
| Wrong package name detected | Fix "name" in composer.json and push |
| New tag not available | Push tag to GitHub, then Update on Packagist |
404 on composer require |
Ensure repo is public and Packagist submit succeeded |
Full reference: docs/PACKAGIST.md
GitHub deployment guide
Use this checklist to publish MigrAlign to GitHub and Packagist.
1) Initialize and connect git
git init
git add .
git commit -m "Initial release: MigrAlign package"
git branch -M main
git remote add origin https://github.com/mokhdesigns/laravel-migralign.git
git push -u origin main
2) Create GitHub repository settings
- set default branch to
main - enable branch protection for
main(require PR + passing checks) - enable security alerts (Dependabot + secret scanning)
- add repository topics:
laravel,migrations,mysql,schema,package
3) Verify CI
This repository includes GitHub Actions at .github/workflows/tests.yml.
After push, verify checks pass in GitHub:
- PHP 8.2 + Laravel 11
- PHP 8.2 + Laravel 12
- PHP 8.3 + Laravel 11
- PHP 8.3 + Laravel 12
- PHP 8.3 + Laravel 13
- PHP 8.4 + Laravel 13
4) Prepare metadata
Before first public release, update links in composer.json:
homepagesupport.issuessupport.sourcefunding.url(optional)
Use your real GitHub repository URL.
5) Tag a release
git tag v1.0.0
git push origin v1.0.0
Then create a GitHub Release for tag v1.0.0.
6) Publish to Packagist
See the full guide: Publish to Packagist.
Quick version:
- Submit
https://github.com/mokhdesigns/laravel-migralignon packagist.org/packages/submit - Enable GitHub auto-update in Packagist settings
- Run
composer require migralign/laravel-migralignin a test Laravel app
7) Post-release checks
- install the package in a clean Laravel app
- run
php artisan migralign:sync --dry-run - verify config publish:
php artisan vendor:publish --tag=migralign-config
Release checklist
-
composer validate --strictpasses -
composer testpasses - README and examples are up to date
- tag created and pushed
- GitHub Release published
- Packagist package updated
Contributing
Contributions are welcome.
Suggested process:
- fork
- create feature branch
- add/adjust tests
- run
composer test - submit PR
License
MIT