PHPackages                             zaeem2396/schema-lens - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. zaeem2396/schema-lens

ActiveLibrary[Database &amp; ORM](/categories/database)

zaeem2396/schema-lens
=====================

Laravel package to preview migration files against current MySQL schema with destructive change detection and data export

v1.6.0(1mo ago)513↓50%MITPHPPHP ^8.1CI failing

Since Dec 26Pushed 1mo agoCompare

[ Source](https://github.com/zaeem2396/schema-lens)[ Packagist](https://packagist.org/packages/zaeem2396/schema-lens)[ RSS](/packages/zaeem2396-schema-lens/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (16)Versions (17)Used By (0)

 [![Schema Lens](assets/logo.png)](assets/logo.png)

 **Preview Laravel migrations before execution with destructive change detection**

 [![Latest Version](https://camo.githubusercontent.com/bc18754f828e144856a164cbfa1b4880560b5fbdc9255b50e2b1adf0c0ac1562/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7a6165656d323339362f736368656d612d6c656e732e737667)](https://packagist.org/packages/zaeem2396/schema-lens) [![Total Downloads](https://camo.githubusercontent.com/7ff60387e80f3d046c0cb1e21f6865461bfd95997a9c4c8f49e44b19d61e2692/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7a6165656d323339362f736368656d612d6c656e732e737667)](https://packagist.org/packages/zaeem2396/schema-lens) [![License](https://camo.githubusercontent.com/6fa37d56460d2059cbb248507b396a75a89da65a32b6c7df559658155cbe1dc6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7a6165656d323339362f736368656d612d6c656e732e737667)](https://github.com/zaeem2396/schema-lens/blob/main/LICENSE)

---

A Laravel package that extends the default Artisan CLI with commands to preview a single migration file against the current MySQL schema before execution. It provides comprehensive schema diff analysis, destructive change detection, automatic data export, and rollback simulation.

**Release highlights:** **v4.6.0** adds `schema:diff` to compare MySQL schemas across two Laravel database connections. **v4.5.0** adds Laravel 13 support. Details: [CHANGELOG.md](CHANGELOG.md).

Features
--------

[](#features)

- 🔍 **Schema Diff Analysis**: Compare migration operations against current MySQL schema
- ⚠️ **Destructive Change Detection**: Automatically flags dangerous operations
- 🔄 **Interactive Mode**: Step-by-step confirmation for destructive changes
- 📄 **Single Migration Support**: Run a specific migration file with full analysis
- 💾 **Automatic Data Export**: Exports affected data to CSV/JSON when destructive changes are detected
- 🔄 **Rollback Simulation**: Preview rollback impact and SQL statements
- 📊 **Line-by-Line Mapping**: Maps each database change back to exact lines in migration file
- 🎨 **Clean CLI Output**: Human-readable formatted output
- 📄 **SQL Preview**: Generate raw SQL statements from migrations
- ⚙️ **Configurable SQL engine**: Set table engine (InnoDB, MyISAM, etc.) for generated SQL via config
- 📊 **Migration Dependency Graph**: Visualize migration dependencies (foreign keys) as ASCII tree or JSON
- 🔀 **Schema diff between environments**: Compare two MySQL connections (missing tables/columns, type mismatches)
- 📄 **JSON Export**: Optional JSON report for CI/CD integration
- 🗜️ **Compression**: Automatic compression of exported data
- 📦 **Versioning**: Automatic versioning of exports with restore metadata

Quick Start
-----------

[](#quick-start)

```
composer require zaeem2396/schema-lens
php artisan schema:preview database/migrations/your_migration.php
# Compare two MySQL connections (optional): php artisan schema:diff mysql mysql_staging
```

📖 **For detailed usage instructions, testing scenarios, and examples, see [USAGE.md](USAGE.md)**

Installation
------------

[](#installation)

```
composer require zaeem2396/schema-lens
```

The package supports:

- **PHP 8.1+**
- **Laravel 10.x through 13.x**

**Schema introspection (diff analysis, destructive detection) requires MySQL.** The `schema:preview` command connects to your database to compare the migration against the current schema. If you use SQLite or another driver locally, use `schema:preview migration.php --sql` to generate SQL without connecting, or run full preview against a MySQL database (e.g. in CI).

**Error output:** When a command fails, only the error message is shown by default. Use `-v` / `--verbose` to see the full stack trace (e.g. for debugging).

Configuration
-------------

[](#configuration)

Publish the configuration file (optional):

```
php artisan vendor:publish --tag=schema-lens-config
```

This will create `config/schema-lens.php` with the following options:

```
return [
    'export' => [
        'row_limit' => env('SCHEMA_LENS_EXPORT_ROW_LIMIT', 1000),
        'storage_path' => 'app/schema-lens/exports',
        'compress' => env('SCHEMA_LENS_COMPRESS_EXPORTS', true),
    ],
    'output' => [
        'format' => env('SCHEMA_LENS_OUTPUT_FORMAT', 'cli'),
        'show_line_numbers' => env('SCHEMA_LENS_SHOW_LINE_NUMBERS', true),
    ],
    'sql' => [
        'engine' => env('SCHEMA_LENS_SQL_ENGINE'), // e.g. InnoDB, MyISAM; falls back to DB connection engine
    ],
];
```

The **SQL engine** (`schema-lens.sql.engine` or `SCHEMA_LENS_SQL_ENGINE`) is used in generated `CREATE TABLE` statements when using `schema:preview --sql`. If not set, the default database connection's engine is used (typically InnoDB).

Usage
-----

[](#usage)

### Basic Usage

[](#basic-usage)

Preview a migration file:

```
php artisan schema:preview database/migrations/2024_01_01_000000_create_users_table.php
```

Or use a relative path from the migrations directory:

```
php artisan schema:preview 2024_01_01_000000_create_users_table.php
```

### SQL Preview

[](#sql-preview)

Generate raw SQL statements that would be executed:

```
# Display SQL in terminal
php artisan schema:preview database/migrations/2024_01_01_000000_create_users_table.php --sql

# Save SQL to file
php artisan schema:preview database/migrations/2024_01_01_000000_create_users_table.php --sql --output=migration.sql

# Or use format option
php artisan schema:preview database/migrations/2024_01_01_000000_create_users_table.php --format=sql
```

The table engine in generated SQL (e.g. `ENGINE=InnoDB`) is configurable via `config/schema-lens.php` → `sql.engine` or the `SCHEMA_LENS_SQL_ENGINE` env variable.

### Migration Dependency Graph

[](#migration-dependency-graph)

Visualize which migrations depend on others (e.g. foreign key relationships):

```
# Default: ASCII tree (uses database/migrations)
php artisan schema:graph

# Custom path
php artisan schema:graph --path=database/migrations

# JSON output
php artisan schema:graph --format=json
```

The graph is derived from `CREATE TABLE` and foreign key operations in each migration. Edges are deduplicated (at most one edge per migration pair). Circular dependencies are detected and reported.

**Exit codes:** If you pass `--path` and that directory is empty or contains no migration files, the command exits with code 1. With the default path, an empty directory yields a warning but exit code 0.

**Options:** `--path` — custom migrations directory; `--format=json` — machine-readable graph. See TESTING-SCENARIOS.md scenario 21 for manual verification steps.

**Example output (CLI):**

```
Migration Dependency Graph

├── 2024_01_01_000000_create_users_table
│   └── 2024_01_06_000000_create_posts_with_foreign_key
└── 2024_01_06_000000_create_posts_with_foreign_key

```

### Schema diff between environments

[](#schema-diff-between-environments)

Compare live MySQL schemas from two Laravel database connections (for example local vs staging). Both connections must use the `mysql` driver and exist in `config/database.php`.

```
php artisan schema:diff mysql mysql_staging

# Named options (same as positional arguments)
php artisan schema:diff --from=mysql --to=mysql_staging

# Machine-readable output
php artisan schema:diff mysql mysql_staging --format=json

# Suggested migration-style hints for gaps (review before using)
php artisan schema:diff mysql mysql_staging --stubs
```

**Exit codes:** The command exits with code **1** when any structural difference is found (missing/extra tables or columns, type or nullable mismatches). Use `--exit-zero` if you only need output in scripts without a failing exit code. It exits 0 when schemas match or when `--exit-zero` is set.

**Example output (CLI):**

```
Schema differences: mysql → mysql_staging
(Reference = mysql; missing below means absent on mysql_staging)

MISSING TABLES ON mysql_staging:
  ✗ Table: user_preferences

TYPE MISMATCH:
  ⚠ posts.body: text (mysql) vs longtext (mysql_staging)

```

**Example output:**

```
╔══════════════════════════════════════════════════════════════╗
║               📄 GENERATED SQL STATEMENTS                    ║
╚══════════════════════════════════════════════════════════════╝

🟢 [1] table::create
CREATE TABLE `users` (...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

🟢 [2] column::add
ALTER TABLE `users` ADD COLUMN `name` VARCHAR(255);

─────────────────────────────────────────────────────────────────
📊 Summary:
   Total statements: 2
   Operations: 🟢 1 create, 🟢 1 add

```

When using `--output`, the SQL file includes:

- Header comments with migration name and timestamp
- `SET FOREIGN_KEY_CHECKS=0/1` wrappers
- Operation comments for each statement

### JSON Output

[](#json-output)

Generate a JSON report for CI/CD:

```
php artisan schema:preview database/migrations/2024_01_01_000000_create_users_table.php --format=json
```

The JSON report will be saved to `storage/app/schema-lens/report.json` by default.

### Skip Data Export

[](#skip-data-export)

If you want to preview without exporting data (even if destructive changes are detected):

```
php artisan schema:preview database/migrations/2024_01_01_000000_create_users_table.php --no-export
```

### Safe Migration (with auto-backup)

[](#safe-migration-with-auto-backup)

Run migrations with automatic destructive change detection and data backup:

```
php artisan migrate:safe
```

**Arguments:**

- `path` - (Optional) Path to a specific migration file to run

**Options:**

- `--force` - Force the operation to run in production
- `--seed` - Run seeders after migration
- `--step` - Run migrations one at a time
- `--pretend` - Dump the SQL queries that would be run
- `--no-backup` - Skip data backup for destructive changes
- `--interactive` - Confirm each destructive change individually

This command:

1. Analyzes all pending migrations for destructive changes
2. Automatically backs up affected data before proceeding
3. Asks for confirmation if destructive changes are detected
4. Runs the actual migration

### Single Migration File

[](#single-migration-file)

Run a specific migration file instead of all pending migrations:

```
# Using relative path
php artisan migrate:safe database/migrations/2024_01_15_drop_column.php

# Using absolute path
php artisan migrate:safe /var/www/app/database/migrations/2024_01_15_drop_column.php
```

This is useful when you:

- Want to analyze and run just one migration
- Need fine-grained control over which migration to execute
- Are testing a specific migration before deploying

You can combine it with other options:

```
# Single file with interactive mode
php artisan migrate:safe database/migrations/2024_01_15_drop_column.php --interactive

# Single file without backup
php artisan migrate:safe database/migrations/2024_01_15_drop_column.php --no-backup

# Single file with pretend mode (just show SQL)
php artisan migrate:safe database/migrations/2024_01_15_drop_column.php --pretend
```

The command validates that:

- The file exists
- It has a `.php` extension
- It hasn't already been executed

### Interactive Mode

[](#interactive-mode)

For granular control over destructive migrations, use interactive mode:

```
php artisan migrate:safe --interactive
```

This prompts you to review each migration with destructive changes individually:

```
📋 Migration: 2024_01_15_drop_email_column.php
   Destructive changes:
   🔴 [CRITICAL] column::drop
      Tables: users
      Columns: users.email

   Approve '2024_01_15_drop_email_column.php'? [y/n/a/s/q]

```

**Options during review:**

KeyAction`y`Approve this migration`n`Skip this migration`a`Approve all remaining migrations`s`Skip all remaining migrations`q`Quit and cancel everythingOnly approved migrations will be executed, giving you full control over which destructive changes to apply.

What It Detects
---------------

[](#what-it-detects)

### Schema Changes

[](#schema-changes)

- **Tables**: Create, modify, drop
- **Columns**: Add, modify, drop, rename
- **Indexes**: Add, drop
- **Foreign Keys**: Add, drop
- **Engine**: Changes
- **Charset**: Changes
- **Collation**: Changes

### Destructive Operations

[](#destructive-operations)

The following operations are flagged as destructive:

- `dropTable()` / `dropIfExists()`
- `dropColumn()` — single `dropColumn('col')` or multiple `dropColumn(['col1','col2'])`
- `dropIndex()`
- `dropForeign()`
- `renameColumn()`
- Constraint removals

Data Export
-----------

[](#data-export)

When destructive changes are detected, Schema Lens automatically:

1. Exports affected table/column data to CSV and JSON
2. Compresses exports (if enabled)
3. Versions the export with metadata
4. Creates restore instructions

### Export Structure

[](#export-structure)

```
storage/app/schema-lens/exports/
└── 2024_01_01_000000_create_users_table_2024-01-15_10-30-45_v0001/
    ├── users.json
    ├── users.csv
    ├── users.zip (if compression enabled)
    └── restore_metadata.json

```

### Restore Metadata

[](#restore-metadata)

Each export includes a `restore_metadata.json` file with:

- Export version and timestamp
- Migration file reference
- Affected tables and columns
- Restore instructions
- File paths for all exported data

Output Examples
---------------

[](#output-examples)

### CLI Output

[](#cli-output)

```
╔══════════════════════════════════════════════════════════════╗
║          Schema Lens - Migration Preview Report            ║
╚══════════════════════════════════════════════════════════════╝

📊 SUMMARY
────────────────────────────────────────────────────────────
Tables:        1
Columns:       5
Indexes:       2
Foreign Keys:  1
Engine:        0
Charset:       0
Collation:     0

⚠️  DESTRUCTIVE CHANGES: 1

⚠️  DESTRUCTIVE CHANGES DETECTED
════════════════════════════════════════════════════════════

  Risk Level: HIGH
  Operation:  column:drop
  Line:       45
  Tables:     users
  Columns:    users.email

📋 DETAILED CHANGES
────────────────────────────────────────────────────────────

📦 TABLES:
  ➕ [Line 12] Will create new table 'users'

📝 COLUMNS:
  ➕ [Line 15] Will add new column 'users.id'
  ➕ [Line 16] Will add new column 'users.name'
  🔴 [Line 45] Will DROP column 'users.email' (DESTRUCTIVE)

🔄 ROLLBACK SIMULATION
────────────────────────────────────────────────────────────
  Risk Level: HIGH
  Columns Affected: users.email

```

### JSON Output

[](#json-output-1)

```
{
    "timestamp": "2024-01-15T10:30:45+00:00",
    "summary": {
        "tables": 1,
        "columns": 5,
        "indexes": 2,
        "foreign_keys": 1,
        "destructive_changes_count": 1,
        "has_destructive_changes": true
    },
    "diff": {
        "tables": [...],
        "columns": [...],
        "indexes": [...],
        "foreign_keys": [...]
    },
    "destructive_changes": [...],
    "rollback": {...},
    "exports": [...]
}
```

Rollback Simulation
-------------------

[](#rollback-simulation)

Schema Lens analyzes the `down()` method of migrations to:

- Show rollback SQL statements
- Identify dependency break risks
- Warn about foreign key constraints
- Highlight affected tables and columns

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10.x–13.x (Laravel 13 requires PHP 8.3+)
- MySQL 5.7+ or MariaDB 10.2+
- Access to `information_schema` database

Environment Variables
---------------------

[](#environment-variables)

You can configure Schema Lens using environment variables:

```
SCHEMA_LENS_EXPORT_ROW_LIMIT=1000
SCHEMA_LENS_COMPRESS_EXPORTS=true
SCHEMA_LENS_OUTPUT_FORMAT=cli
SCHEMA_LENS_SHOW_LINE_NUMBERS=true
```

CI/CD Integration
-----------------

[](#cicd-integration)

### GitHub Actions Example

[](#github-actions-example)

```
- name: Preview Migration
  run: |
    php artisan schema:preview database/migrations/2024_01_01_000000_create_users_table.php --format=json
    cat storage/app/schema-lens/report.json | jq '.destructive_changes'
```

### GitLab CI Example

[](#gitlab-ci-example)

```
migration-preview:
  script:
    - php artisan schema:preview database/migrations/2024_01_01_000000_create_users_table.php --format=json
    - |
      if [ $(cat storage/app/schema-lens/report.json | jq '.summary.has_destructive_changes') = "true" ]; then
        echo "⚠️ Destructive changes detected!"
        exit 1
      fi
```

Troubleshooting
---------------

[](#troubleshooting)

- **"Schema Lens schema introspection requires MySQL"** — Use `schema:preview migration.php --sql` to generate SQL without connecting, or run the command against a MySQL database (e.g. in CI).
- **Debugging command failures** — Use `-v` or `--verbose` to see the full stack trace.
- **Custom table engine in generated SQL** — Set `SCHEMA_LENS_SQL_ENGINE` or `config/schema-lens.sql.engine` (e.g. `MyISAM`) to override the engine in `CREATE TABLE` output.
- **`schema:diff` requires two MySQL connections** — Add both to `config/database.php`; SQLite or other drivers are rejected for this command.
- **`schema:diff` exits 1 on drift** — Use `--exit-zero` in CI if you only want logs without failing the job.

Limitations
-----------

[](#limitations)

- `schema:diff` compares **structure** only (tables/columns/types), not row data or triggers
- Currently supports MySQL/MariaDB only
- Requires direct database connection (no cloud services)
- Schema introspection uses `information_schema` tables
- Migration parser supports standard Laravel migration syntax

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

License
-------

[](#license)

This package is open-sourced software licensed under the [MIT license](LICENSE).

Author
------

[](#author)

**zaeem2396**

GitHub: [@zaeem2396](https://github.com/zaeem2396)

Support
-------

[](#support)

For issues, questions, or contributions, please open an issue on GitHub.

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance92

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 99.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~8 days

Total

12

Last Release

39d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c2da070ec066ea427f578b46c3ae6a1f97220e75daeaa4c8a9456ffad75fa5bb?d=identicon)[zaeem2396](/maintainers/zaeem2396)

---

Top Contributors

[![zaeem2396](https://avatars.githubusercontent.com/u/31367343?v=4)](https://github.com/zaeem2396 "zaeem2396 (133 commits)")[![cod3xa](https://avatars.githubusercontent.com/u/219617529?v=4)](https://github.com/cod3xa "cod3xa (1 commits)")

---

Tags

clilaravelschemamigrationdatabasemysqlartisanpreviewenvironmentsdata-exportdestructive-changesschema-diff

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/zaeem2396-schema-lens/health.svg)

```
[![Health](https://phpackages.com/badges/zaeem2396-schema-lens/health.svg)](https://phpackages.com/packages/zaeem2396-schema-lens)
```

###  Alternatives

[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[cybercog/laravel-clickhouse

ClickHouse migrations for Laravel

163166.8k](/packages/cybercog-laravel-clickhouse)[toponepercent/baum

Baum is an implementation of the Nested Set pattern for Eloquent models.

3154.7k](/packages/toponepercent-baum)[dragon-code/laravel-data-dumper

Adding data from certain tables when executing the `php artisan schema:dump` console command

3418.6k](/packages/dragon-code-laravel-data-dumper)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
